diff --git a/setup/website_slides_require_completion/odoo/addons/website_slides_require_completion b/setup/website_slides_require_completion/odoo/addons/website_slides_require_completion new file mode 120000 index 0000000..b3d89f9 --- /dev/null +++ b/setup/website_slides_require_completion/odoo/addons/website_slides_require_completion @@ -0,0 +1 @@ +../../../../website_slides_require_completion \ No newline at end of file diff --git a/setup/website_slides_require_completion/setup.py b/setup/website_slides_require_completion/setup.py new file mode 100644 index 0000000..28c57bb --- /dev/null +++ b/setup/website_slides_require_completion/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +) diff --git a/website_slides_require_completion/README.rst b/website_slides_require_completion/README.rst new file mode 100644 index 0000000..7d3026e --- /dev/null +++ b/website_slides_require_completion/README.rst @@ -0,0 +1,93 @@ +=================================================== +Courses's Slides Require Previous Slides Completion +=================================================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:ee4378b92b13f8ef9d5e45aaa9ac42feeeba2a7ac88e5d58c1b60bea420e0853 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fe--learning-lightgray.png?logo=github + :target: https://github.com/OCA/e-learning/tree/16.0/website_slides_require_completion + :alt: OCA/e-learning +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/e-learning-16-0/e-learning-16-0-website_slides_require_completion + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/e-learning&target_branch=16.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module allows you to enforce the completion of previous slides before accessing the next one in an e-learning course. + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +To use this module, you need to: + +#. Go to an e-learning course form view "Options" tab +#. Under the "Display" section, check the "Require previous slides completion" option + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* Binhex + +Contributors +~~~~~~~~~~~~ + +* Adasat Torres de León +* Rolando Pérez Rebollo + +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +.. |maintainer-adasatorres| image:: https://github.com/adasatorres.png?size=40px + :target: https://github.com/adasatorres + :alt: adasatorres + +Current `maintainer `__: + +|maintainer-adasatorres| + +This module is part of the `OCA/e-learning `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/website_slides_require_completion/__init__.py b/website_slides_require_completion/__init__.py new file mode 100644 index 0000000..d6bd80e --- /dev/null +++ b/website_slides_require_completion/__init__.py @@ -0,0 +1,5 @@ +# Copyright 2025 Binhex - Adasat Torres de León +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import models +from . import controllers diff --git a/website_slides_require_completion/__manifest__.py b/website_slides_require_completion/__manifest__.py new file mode 100644 index 0000000..eb54856 --- /dev/null +++ b/website_slides_require_completion/__manifest__.py @@ -0,0 +1,28 @@ +# Copyright 2025 Binhex - Adasat Torres de León +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +{ + "name": "Courses's Slides Require Previous Slides Completion", + "summary": """If checked, the user has to complete previous slides before """ + """moving to the next one.""", + "version": "16.0.1.0.0", + "category": "Website/eLearning", + "author": "Binhex, Odoo Community Association (OCA)", + "website": "https://github.com/OCA/e-learning", + "depends": ["web", "website_slides"], + "data": [ + "views/slide_channel_views.xml", + "views/website_slides_templates_course.xml", + "views/website_slides_templates_lesson_fullscreen.xml", + "views/website_slides_templates_lesson_embed.xml", + "views/website_slides_templates_utils.xml", + ], + "assets": { + "web.assets_frontend": [ + "website_slides_require_completion/static/src/js/*.js", + "website_slides_require_completion/static/src/xml/*.xml", + ], + }, + "license": "AGPL-3", + "maintainers": ["adasatorres"], +} diff --git a/website_slides_require_completion/controllers/__init__.py b/website_slides_require_completion/controllers/__init__.py new file mode 100644 index 0000000..12a7e52 --- /dev/null +++ b/website_slides_require_completion/controllers/__init__.py @@ -0,0 +1 @@ +from . import main diff --git a/website_slides_require_completion/controllers/main.py b/website_slides_require_completion/controllers/main.py new file mode 100644 index 0000000..ec5140f --- /dev/null +++ b/website_slides_require_completion/controllers/main.py @@ -0,0 +1,17 @@ +# Copyright 2025 Binhex - Adasat Torres de León +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +from odoo.http import request, route + +from odoo.addons.website_slides.controllers.main import WebsiteSlides + + +class WebsiteSlidesRequireCompletion(WebsiteSlides): + @route( + "/slides/channel/require_completion", type="json", auth="user", methods=["POST"] + ) + def require_completion(self, slide_id): + """ + Check if the chanell of the slide requires completion. + """ + slide = request.env["slide.slide"].sudo().browse(slide_id) + return {"is_required": slide.channel_id.require_slides_completion} diff --git a/website_slides_require_completion/models/__init__.py b/website_slides_require_completion/models/__init__.py new file mode 100644 index 0000000..7db5f04 --- /dev/null +++ b/website_slides_require_completion/models/__init__.py @@ -0,0 +1,4 @@ +# Copyright 2025 Binhex - Adasat Torres de León +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +from . import slide_channel +from . import slide_slide diff --git a/website_slides_require_completion/models/slide_channel.py b/website_slides_require_completion/models/slide_channel.py new file mode 100644 index 0000000..47fc4ca --- /dev/null +++ b/website_slides_require_completion/models/slide_channel.py @@ -0,0 +1,14 @@ +# Copyright 2025 Binhex - Adasat Torres de León +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +from odoo import fields, models + + +class SlideChannel(models.Model): + _inherit = "slide.channel" + + require_slides_completion = fields.Boolean( + string="Require previous slides completion", + help="""If checked, the user has to complete previous slides before """ + """moving to the next one""", + default=False, + ) diff --git a/website_slides_require_completion/models/slide_slide.py b/website_slides_require_completion/models/slide_slide.py new file mode 100644 index 0000000..63a5390 --- /dev/null +++ b/website_slides_require_completion/models/slide_slide.py @@ -0,0 +1,28 @@ +# Copyright 2025 Binhex - Adasat Torres de León +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +from odoo import fields, models + + +class SlideSlide(models.Model): + _inherit = "slide.slide" + + is_blocked = fields.Boolean(compute="_compute_is_blocked", compute_sudo=False) + + def _get_previous_slide(self): + return self.search( + [ + ("is_category", "=", False), + ("sequence", "<", self.sequence), + ("channel_id", "=", self.channel_id.id), + ], + order="sequence desc", + limit=1, + ) + + def _compute_is_blocked(self): + for slide in self: + previous_slide = slide._get_previous_slide() + if not previous_slide or not slide.channel_id.require_slides_completion: + slide.is_blocked = False + else: + slide.is_blocked = not previous_slide.user_has_completed diff --git a/website_slides_require_completion/readme/CONTRIBUTORS.rst b/website_slides_require_completion/readme/CONTRIBUTORS.rst new file mode 100644 index 0000000..340dec9 --- /dev/null +++ b/website_slides_require_completion/readme/CONTRIBUTORS.rst @@ -0,0 +1,2 @@ +* Adasat Torres de León +* Rolando Pérez Rebollo diff --git a/website_slides_require_completion/readme/DESCRIPTION.rst b/website_slides_require_completion/readme/DESCRIPTION.rst new file mode 100644 index 0000000..374ab04 --- /dev/null +++ b/website_slides_require_completion/readme/DESCRIPTION.rst @@ -0,0 +1 @@ +This module allows you to enforce the completion of previous slides before accessing the next one in an e-learning course. diff --git a/website_slides_require_completion/readme/USAGE.rst b/website_slides_require_completion/readme/USAGE.rst new file mode 100644 index 0000000..3f6545c --- /dev/null +++ b/website_slides_require_completion/readme/USAGE.rst @@ -0,0 +1,4 @@ +To use this module, you need to: + +#. Go to an e-learning course form view "Options" tab +#. Under the "Display" section, check the "Require previous slides completion" option diff --git a/website_slides_require_completion/static/description/icon.png b/website_slides_require_completion/static/description/icon.png new file mode 100644 index 0000000..3a0328b Binary files /dev/null and b/website_slides_require_completion/static/description/icon.png differ diff --git a/website_slides_require_completion/static/description/index.html b/website_slides_require_completion/static/description/index.html new file mode 100644 index 0000000..4e324be --- /dev/null +++ b/website_slides_require_completion/static/description/index.html @@ -0,0 +1,435 @@ + + + + + +Courses's Slides Require Previous Slides Completion + + + +
+

Courses’s Slides Require Previous Slides Completion

+ + +

Beta License: AGPL-3 OCA/e-learning Translate me on Weblate Try me on Runboat

+

This module allows you to enforce the completion of previous slides before accessing the next one in an e-learning course.

+

Table of contents

+ +
+

Usage

+

To use this module, you need to:

+
    +
  1. Go to an e-learning course form view “Options” tab
  2. +
  3. Under the “Display” section, check the “Require previous slides completion” option
  4. +
+
+
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Binhex
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+ +Odoo Community Association + +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

Current maintainer:

+

adasatorres

+

This module is part of the OCA/e-learning project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/website_slides_require_completion/static/src/js/slides_course_page.esm.js b/website_slides_require_completion/static/src/js/slides_course_page.esm.js new file mode 100644 index 0000000..d9d3f77 --- /dev/null +++ b/website_slides_require_completion/static/src/js/slides_course_page.esm.js @@ -0,0 +1,33 @@ +/** @odoo-module **/ + +import {SlideCoursePage} from "@website_slides/js/slides_course_page"; +import {patch} from "@web/core/utils/patch"; +patch( + SlideCoursePage.prototype, + "website_slides_require_completion.slides_course_page", + { + toggleCompletionButton: function (slide, completed = true) { + this._super.apply(this, arguments); + const self = this; + this._rpc({ + route: "/slides/channel/require_completion", + params: {slide_id: slide.id}, + }) + .then((data) => { + if ( + self._parseBoolean(slide.completed) != completed && + data.is_required + ) { + window.location.reload(); + } + }) + .guardedCatch((err) => { + console.error("ERROR en RPC:", err); + }); + }, + + _parseBoolean: function (str) { + return typeof str === "string" && str.toLowerCase() === "true"; + }, + } +); diff --git a/website_slides_require_completion/tests/__init__.py b/website_slides_require_completion/tests/__init__.py new file mode 100644 index 0000000..6275ca0 --- /dev/null +++ b/website_slides_require_completion/tests/__init__.py @@ -0,0 +1 @@ +from . import test_slide_require_completion diff --git a/website_slides_require_completion/tests/test_slide_require_completion.py b/website_slides_require_completion/tests/test_slide_require_completion.py new file mode 100644 index 0000000..d89fa65 --- /dev/null +++ b/website_slides_require_completion/tests/test_slide_require_completion.py @@ -0,0 +1,40 @@ +# Copyright 2025 Binhex - Adasat Torres de León +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +import json +import logging + +from odoo.tests import tagged +from odoo.tests.common import HttpCase + +from odoo.addons.website_slides.tests.common import SlidesCase + +_logger = logging.getLogger(__name__) + + +@tagged("post_install", "-at_install") +class TestSlideRequireCompletion(SlidesCase, HttpCase): + def test_01_require_completion(self): + self.channel.write({"require_slides_completion": True}) + self.slide._compute_is_blocked() + self.assertFalse(self.slide.is_blocked) + self.slide_2._compute_is_blocked() + self.assertTrue(self.slide_2.is_blocked) + + def test_02_require_completion_previous_slide_completed(self): + self.channel.write({"require_slides_completion": True}) + self.authenticate("admin", "admin") + data = json.dumps( + { + "id": 0, + "jsonrpc": "2.0", + "method": "call", + "params": {"slide_id": self.slide_2.id}, + } + ).encode() + response = self.url_open( + "/slides/channel/require_completion", + data=data, + headers={"Content-Type": "application/json"}, + ) + result = response.json()["result"] + self.assertEqual(result, {"is_required": True}) diff --git a/website_slides_require_completion/views/slide_channel_views.xml b/website_slides_require_completion/views/slide_channel_views.xml new file mode 100644 index 0000000..ad721d3 --- /dev/null +++ b/website_slides_require_completion/views/slide_channel_views.xml @@ -0,0 +1,13 @@ + + + + slide.channel.view.form + slide.channel + + + + + + + + diff --git a/website_slides_require_completion/views/website_slides_templates_course.xml b/website_slides_require_completion/views/website_slides_templates_course.xml new file mode 100644 index 0000000..15113ec --- /dev/null +++ b/website_slides_require_completion/views/website_slides_templates_course.xml @@ -0,0 +1,17 @@ + + + + diff --git a/website_slides_require_completion/views/website_slides_templates_lesson_embed.xml b/website_slides_require_completion/views/website_slides_templates_lesson_embed.xml new file mode 100644 index 0000000..61f2e03 --- /dev/null +++ b/website_slides_require_completion/views/website_slides_templates_lesson_embed.xml @@ -0,0 +1,13 @@ + + + + diff --git a/website_slides_require_completion/views/website_slides_templates_lesson_fullscreen.xml b/website_slides_require_completion/views/website_slides_templates_lesson_fullscreen.xml new file mode 100644 index 0000000..dc7b38e --- /dev/null +++ b/website_slides_require_completion/views/website_slides_templates_lesson_fullscreen.xml @@ -0,0 +1,13 @@ + + + + diff --git a/website_slides_require_completion/views/website_slides_templates_utils.xml b/website_slides_require_completion/views/website_slides_templates_utils.xml new file mode 100644 index 0000000..8927ffa --- /dev/null +++ b/website_slides_require_completion/views/website_slides_templates_utils.xml @@ -0,0 +1,24 @@ + + + +