From b16e6435638bf7e10fa10063f9a4f206e871eef9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9ry=20Debongnie?= Date: Sun, 9 Oct 2022 20:21:18 +0200 Subject: [PATCH 1/4] [ADD] Discover the JavaScript framework --- README.md | 12 +++--- awesome_clicker/__init__.py | 1 + awesome_clicker/__manifest__.py | 29 +++++++++++++ awesome_dashboard/__init__.py | 3 ++ awesome_dashboard/__manifest__.py | 30 +++++++++++++ awesome_dashboard/controllers/__init__.py | 3 ++ awesome_dashboard/controllers/controllers.py | 36 ++++++++++++++++ awesome_dashboard/static/src/dashboard.js | 10 +++++ awesome_dashboard/static/src/dashboard.xml | 8 ++++ awesome_dashboard/views/views.xml | 11 +++++ awesome_gallery/__init__.py | 2 + awesome_gallery/__manifest__.py | 26 ++++++++++++ awesome_gallery/models/__init__.py | 4 ++ awesome_gallery/models/ir_action.py | 10 +++++ awesome_gallery/models/ir_ui_view.py | 8 ++++ awesome_gallery/static/src/gallery_view.js | 3 ++ awesome_gallery/views/views.xml | 19 +++++++++ awesome_kanban/__init__.py | 1 + awesome_kanban/__manifest__.py | 26 ++++++++++++ .../static/src/awesome_kanban_view.js | 3 ++ awesome_kanban/views/views.xml | 15 +++++++ awesome_owl/__init__.py | 3 ++ awesome_owl/__manifest__.py | 42 +++++++++++++++++++ awesome_owl/controllers/__init__.py | 3 ++ awesome_owl/controllers/controllers.py | 10 +++++ awesome_owl/static/src/main.js | 11 +++++ awesome_owl/static/src/playground.js | 7 ++++ awesome_owl/static/src/playground.xml | 10 +++++ awesome_owl/views/templates.xml | 15 +++++++ 29 files changed, 355 insertions(+), 6 deletions(-) create mode 100644 awesome_clicker/__init__.py create mode 100644 awesome_clicker/__manifest__.py create mode 100644 awesome_dashboard/__init__.py create mode 100644 awesome_dashboard/__manifest__.py create mode 100644 awesome_dashboard/controllers/__init__.py create mode 100644 awesome_dashboard/controllers/controllers.py create mode 100644 awesome_dashboard/static/src/dashboard.js create mode 100644 awesome_dashboard/static/src/dashboard.xml create mode 100644 awesome_dashboard/views/views.xml create mode 100644 awesome_gallery/__init__.py create mode 100644 awesome_gallery/__manifest__.py create mode 100644 awesome_gallery/models/__init__.py create mode 100644 awesome_gallery/models/ir_action.py create mode 100644 awesome_gallery/models/ir_ui_view.py create mode 100644 awesome_gallery/static/src/gallery_view.js create mode 100644 awesome_gallery/views/views.xml create mode 100644 awesome_kanban/__init__.py create mode 100644 awesome_kanban/__manifest__.py create mode 100644 awesome_kanban/static/src/awesome_kanban_view.js create mode 100644 awesome_kanban/views/views.xml create mode 100644 awesome_owl/__init__.py create mode 100644 awesome_owl/__manifest__.py create mode 100644 awesome_owl/controllers/__init__.py create mode 100644 awesome_owl/controllers/controllers.py create mode 100644 awesome_owl/static/src/main.js create mode 100644 awesome_owl/static/src/playground.js create mode 100644 awesome_owl/static/src/playground.xml create mode 100644 awesome_owl/views/templates.xml diff --git a/README.md b/README.md index 0c6667bb6f2..89e6a2b2296 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ # Odoo tutorials This repository hosts the code for the bases and solutions of the -[official Odoo tutorials](https://www.odoo.com/documentation/16.0/developer/howtos.html). +[official Odoo tutorials](https://www.odoo.com/documentation/17.0/developer/tutorials.html). -It has 2 branches for each Odoo version: one for the bases and one for -the solutions. For example, `16.0` and `16.0-solutions`. The first -contains the code of the modules that serve as base for the tutorials, -and the second contains the code of the same modules with the complete -solution. \ No newline at end of file +It has 3 branches for each Odoo version: one for the bases, one for +[Discover the JS framework](https://www.odoo.com/documentation/17.0/developer/tutorials/discover_js_framework.html) solutions and one for [Master the Odoo web framework](https://www.odoo.com/documentation/17.0/developer/tutorials/master_odoo_web_framework.html) solutions. For example, `17.0`, `17.0-discover-js-framework-solutions` and `17.0-master-odoo-web-framework-solutions`. +The first contains the code of the modules that serve as base for the tutorials, +and the others contains the code of each chapter with the complete +solution. diff --git a/awesome_clicker/__init__.py b/awesome_clicker/__init__.py new file mode 100644 index 00000000000..40a96afc6ff --- /dev/null +++ b/awesome_clicker/__init__.py @@ -0,0 +1 @@ +# -*- coding: utf-8 -*- diff --git a/awesome_clicker/__manifest__.py b/awesome_clicker/__manifest__.py new file mode 100644 index 00000000000..e57ef4d5bb0 --- /dev/null +++ b/awesome_clicker/__manifest__.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- +{ + 'name': "Awesome Clicker", + + 'summary': """ + Starting module for "Master the Odoo web framework, chapter 1: Build a Clicker game" + """, + + 'description': """ + Starting module for "Master the Odoo web framework, chapter 1: Build a Clicker game" + """, + + 'author': "Odoo", + 'website': "https://www.odoo.com/", + 'category': 'Tutorials/AwesomeClicker', + 'version': '0.1', + 'application': True, + 'installable': True, + 'depends': ['base', 'web'], + + 'data': [], + 'assets': { + 'web.assets_backend': [ + 'awesome_clicker/static/src/**/*', + ], + + }, + 'license': 'AGPL-3' +} diff --git a/awesome_dashboard/__init__.py b/awesome_dashboard/__init__.py new file mode 100644 index 00000000000..b0f26a9a602 --- /dev/null +++ b/awesome_dashboard/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- + +from . import controllers diff --git a/awesome_dashboard/__manifest__.py b/awesome_dashboard/__manifest__.py new file mode 100644 index 00000000000..31406e8addb --- /dev/null +++ b/awesome_dashboard/__manifest__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +{ + 'name': "Awesome Dashboard", + + 'summary': """ + Starting module for "Discover the JS framework, chapter 2: Build a dashboard" + """, + + 'description': """ + Starting module for "Discover the JS framework, chapter 2: Build a dashboard" + """, + + 'author': "Odoo", + 'website': "https://www.odoo.com/", + 'category': 'Tutorials/AwesomeDashboard', + 'version': '0.1', + 'application': True, + 'installable': True, + 'depends': ['base', 'web', 'mail', 'crm'], + + 'data': [ + 'views/views.xml', + ], + 'assets': { + 'web.assets_backend': [ + 'awesome_dashboard/static/src/**/*', + ], + }, + 'license': 'AGPL-3' +} diff --git a/awesome_dashboard/controllers/__init__.py b/awesome_dashboard/controllers/__init__.py new file mode 100644 index 00000000000..457bae27e11 --- /dev/null +++ b/awesome_dashboard/controllers/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- + +from . import controllers \ No newline at end of file diff --git a/awesome_dashboard/controllers/controllers.py b/awesome_dashboard/controllers/controllers.py new file mode 100644 index 00000000000..56d4a051287 --- /dev/null +++ b/awesome_dashboard/controllers/controllers.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- + +import logging +import random + +from odoo import http +from odoo.http import request + +logger = logging.getLogger(__name__) + +class AwesomeDashboard(http.Controller): + @http.route('/awesome_dashboard/statistics', type='json', auth='user') + def get_statistics(self): + """ + Returns a dict of statistics about the orders: + 'average_quantity': the average number of t-shirts by order + 'average_time': the average time (in hours) elapsed between the + moment an order is created, and the moment is it sent + 'nb_cancelled_orders': the number of cancelled orders, this month + 'nb_new_orders': the number of new orders, this month + 'total_amount': the total amount of orders, this month + """ + + return { + 'average_quantity': random.randint(4, 12), + 'average_time': random.randint(4, 123), + 'nb_cancelled_orders': random.randint(0, 50), + 'nb_new_orders': random.randint(10, 200), + 'orders_by_size': { + 'm': random.randint(0, 150), + 's': random.randint(0, 150), + 'xl': random.randint(0, 150), + }, + 'total_amount': random.randint(100, 1000) + } + diff --git a/awesome_dashboard/static/src/dashboard.js b/awesome_dashboard/static/src/dashboard.js new file mode 100644 index 00000000000..637fa4bb972 --- /dev/null +++ b/awesome_dashboard/static/src/dashboard.js @@ -0,0 +1,10 @@ +/** @odoo-module **/ + +import { Component } from "@odoo/owl"; +import { registry } from "@web/core/registry"; + +class AwesomeDashboard extends Component { + static template = "awesome_dashboard.AwesomeDashboard"; +} + +registry.category("actions").add("awesome_dashboard.dashboard", AwesomeDashboard); diff --git a/awesome_dashboard/static/src/dashboard.xml b/awesome_dashboard/static/src/dashboard.xml new file mode 100644 index 00000000000..1a2ac9a2fed --- /dev/null +++ b/awesome_dashboard/static/src/dashboard.xml @@ -0,0 +1,8 @@ + + + + + hello dashboard + + + diff --git a/awesome_dashboard/views/views.xml b/awesome_dashboard/views/views.xml new file mode 100644 index 00000000000..47fb2b6f258 --- /dev/null +++ b/awesome_dashboard/views/views.xml @@ -0,0 +1,11 @@ + + + + Dashboard + awesome_dashboard.dashboard + + + + + + diff --git a/awesome_gallery/__init__.py b/awesome_gallery/__init__.py new file mode 100644 index 00000000000..a0fdc10fe11 --- /dev/null +++ b/awesome_gallery/__init__.py @@ -0,0 +1,2 @@ +# -*- coding: utf-8 -*- +from . import models diff --git a/awesome_gallery/__manifest__.py b/awesome_gallery/__manifest__.py new file mode 100644 index 00000000000..624766dca89 --- /dev/null +++ b/awesome_gallery/__manifest__.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +{ + 'name': "Gallery View", + 'summary': """ + Starting module for "Master the Odoo web framework, chapter 3: Create a Gallery View" + """, + + 'description': """ + Starting module for "Master the Odoo web framework, chapter 3: Create a Gallery View" + """, + + 'version': '0.1', + 'application': True, + 'category': 'Tutorials/AwesomeGallery', + 'installable': True, + 'depends': ['web', 'contacts'], + 'data': [ + 'views/views.xml', + ], + 'assets': { + 'web.assets_backend': [ + 'awesome_gallery/static/src/**/*', + ], + }, + 'license': 'AGPL-3' +} diff --git a/awesome_gallery/models/__init__.py b/awesome_gallery/models/__init__.py new file mode 100644 index 00000000000..7f0930ee744 --- /dev/null +++ b/awesome_gallery/models/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- +# import filename_python_file_within_folder_or_subfolder +from . import ir_action +from . import ir_ui_view diff --git a/awesome_gallery/models/ir_action.py b/awesome_gallery/models/ir_action.py new file mode 100644 index 00000000000..eae20acbf5c --- /dev/null +++ b/awesome_gallery/models/ir_action.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +from odoo import fields, models + + +class ActWindowView(models.Model): + _inherit = 'ir.actions.act_window.view' + + view_mode = fields.Selection(selection_add=[ + ('gallery', "Awesome Gallery") + ], ondelete={'gallery': 'cascade'}) diff --git a/awesome_gallery/models/ir_ui_view.py b/awesome_gallery/models/ir_ui_view.py new file mode 100644 index 00000000000..0c11b8298ac --- /dev/null +++ b/awesome_gallery/models/ir_ui_view.py @@ -0,0 +1,8 @@ +# -*- coding: utf-8 -*- +from odoo import fields, models + + +class View(models.Model): + _inherit = 'ir.ui.view' + + type = fields.Selection(selection_add=[('gallery', "Awesome Gallery")]) diff --git a/awesome_gallery/static/src/gallery_view.js b/awesome_gallery/static/src/gallery_view.js new file mode 100644 index 00000000000..db904d1f478 --- /dev/null +++ b/awesome_gallery/static/src/gallery_view.js @@ -0,0 +1,3 @@ +/** @odoo-module */ + +// TODO: Begin here! diff --git a/awesome_gallery/views/views.xml b/awesome_gallery/views/views.xml new file mode 100644 index 00000000000..56327365875 --- /dev/null +++ b/awesome_gallery/views/views.xml @@ -0,0 +1,19 @@ + + + + + Contacts + res.partner + kanban,tree,form,activity + + {'default_is_company': True} + +

+ Create a Contact in your address book +

+ Odoo helps you track all activities related to your contacts. +

+
+
+
+
diff --git a/awesome_kanban/__init__.py b/awesome_kanban/__init__.py new file mode 100644 index 00000000000..40a96afc6ff --- /dev/null +++ b/awesome_kanban/__init__.py @@ -0,0 +1 @@ +# -*- coding: utf-8 -*- diff --git a/awesome_kanban/__manifest__.py b/awesome_kanban/__manifest__.py new file mode 100644 index 00000000000..affef78bb12 --- /dev/null +++ b/awesome_kanban/__manifest__.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +{ + 'name': "Awesome Kanban", + 'summary': """ + Starting module for "Master the Odoo web framework, chapter 4: Customize a kanban view" + """, + + 'description': """ + Starting module for "Master the Odoo web framework, chapter 4: Customize a kanban view. + """, + + 'version': '0.1', + 'application': True, + 'category': 'Tutorials/AwesomeKanban', + 'installable': True, + 'depends': ['web', 'crm'], + 'data': [ + 'views/views.xml', + ], + 'assets': { + 'web.assets_backend': [ + 'awesome_kanban/static/src/**/*', + ], + }, + 'license': 'AGPL-3' +} diff --git a/awesome_kanban/static/src/awesome_kanban_view.js b/awesome_kanban/static/src/awesome_kanban_view.js new file mode 100644 index 00000000000..9f33fc1300b --- /dev/null +++ b/awesome_kanban/static/src/awesome_kanban_view.js @@ -0,0 +1,3 @@ +/** @odoo-module */ + +// TODO: Define here your AwesomeKanban view diff --git a/awesome_kanban/views/views.xml b/awesome_kanban/views/views.xml new file mode 100644 index 00000000000..548b2907b6e --- /dev/null +++ b/awesome_kanban/views/views.xml @@ -0,0 +1,15 @@ + + + + + crm.lead.kanban.lead.awesome_gallery + crm.lead + + + + awesome_kanban + + + + + diff --git a/awesome_owl/__init__.py b/awesome_owl/__init__.py new file mode 100644 index 00000000000..457bae27e11 --- /dev/null +++ b/awesome_owl/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- + +from . import controllers \ No newline at end of file diff --git a/awesome_owl/__manifest__.py b/awesome_owl/__manifest__.py new file mode 100644 index 00000000000..77abad510ef --- /dev/null +++ b/awesome_owl/__manifest__.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +{ + 'name': "Awesome Owl", + + 'summary': """ + Starting module for "Discover the JS framework, chapter 1: Owl components" + """, + + 'description': """ + Starting module for "Discover the JS framework, chapter 1: Owl components" + """, + + 'author': "Odoo", + 'website': "https://www.odoo.com", + + # Categories can be used to filter modules in modules listing + # Check https://github.com/odoo/odoo/blob/15.0/odoo/addons/base/data/ir_module_category_data.xml + # for the full list + 'category': 'Tutorials/AwesomeOwl', + 'version': '0.1', + + # any module necessary for this one to work correctly + 'depends': ['base', 'web'], + 'application': True, + 'installable': True, + 'data': [ + 'views/templates.xml', + ], + 'assets': { + 'awesome_owl.assets_playground': [ + ('include', 'web._assets_helpers'), + 'web/static/src/scss/pre_variables.scss', + 'web/static/lib/bootstrap/scss/_variables.scss', + 'web/static/lib/bootstrap/scss/_maps.scss', + ('include', 'web._assets_bootstrap'), + ('include', 'web._assets_core'), + 'web/static/src/libs/fontawesome/css/font-awesome.css', + 'awesome_owl/static/src/**/*', + ], + }, + 'license': 'AGPL-3' +} diff --git a/awesome_owl/controllers/__init__.py b/awesome_owl/controllers/__init__.py new file mode 100644 index 00000000000..457bae27e11 --- /dev/null +++ b/awesome_owl/controllers/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- + +from . import controllers \ No newline at end of file diff --git a/awesome_owl/controllers/controllers.py b/awesome_owl/controllers/controllers.py new file mode 100644 index 00000000000..bccfd6fe283 --- /dev/null +++ b/awesome_owl/controllers/controllers.py @@ -0,0 +1,10 @@ +from odoo import http +from odoo.http import request, route + +class OwlPlayground(http.Controller): + @http.route(['/awesome_owl'], type='http', auth='public') + def show_playground(self): + """ + Renders the owl playground page + """ + return request.render('awesome_owl.playground') diff --git a/awesome_owl/static/src/main.js b/awesome_owl/static/src/main.js new file mode 100644 index 00000000000..1af6c827e0b --- /dev/null +++ b/awesome_owl/static/src/main.js @@ -0,0 +1,11 @@ +import { whenReady } from "@odoo/owl"; +import { mountComponent } from "@web/env"; +import { Playground } from "./playground"; + +const config = { + dev: true, + name: "Owl Tutorial", +}; + +// Mount the Playground component when the document.body is ready +whenReady(() => mountComponent(Playground, document.body, config)); diff --git a/awesome_owl/static/src/playground.js b/awesome_owl/static/src/playground.js new file mode 100644 index 00000000000..657fb8b07bb --- /dev/null +++ b/awesome_owl/static/src/playground.js @@ -0,0 +1,7 @@ +/** @odoo-module **/ + +import { Component } from "@odoo/owl"; + +export class Playground extends Component { + static template = "awesome_owl.playground"; +} diff --git a/awesome_owl/static/src/playground.xml b/awesome_owl/static/src/playground.xml new file mode 100644 index 00000000000..4fb905d59f9 --- /dev/null +++ b/awesome_owl/static/src/playground.xml @@ -0,0 +1,10 @@ + + + + +
+ hello world +
+
+ +
diff --git a/awesome_owl/views/templates.xml b/awesome_owl/views/templates.xml new file mode 100644 index 00000000000..aa54c1a7241 --- /dev/null +++ b/awesome_owl/views/templates.xml @@ -0,0 +1,15 @@ + + + + + From 4f1d2554d6e399c49fb53ae2c7224c91a87aec26 Mon Sep 17 00:00:00 2001 From: "Antoine Vandevenne (anv)" Date: Tue, 19 Nov 2024 16:55:51 +0100 Subject: [PATCH 2/4] [IMP] README: update the repository's description --- README.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 89e6a2b2296..c80c29b24c8 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,11 @@ # Odoo tutorials -This repository hosts the code for the bases and solutions of the -[official Odoo tutorials](https://www.odoo.com/documentation/17.0/developer/tutorials.html). +This repository hosts the code for the bases of the modules used in the +[official Odoo tutorials](https://www.odoo.com/documentation/lastest/developer/tutorials.html). -It has 3 branches for each Odoo version: one for the bases, one for -[Discover the JS framework](https://www.odoo.com/documentation/17.0/developer/tutorials/discover_js_framework.html) solutions and one for [Master the Odoo web framework](https://www.odoo.com/documentation/17.0/developer/tutorials/master_odoo_web_framework.html) solutions. For example, `17.0`, `17.0-discover-js-framework-solutions` and `17.0-master-odoo-web-framework-solutions`. -The first contains the code of the modules that serve as base for the tutorials, -and the others contains the code of each chapter with the complete -solution. +It has 3 branches for each Odoo version: one for the bases, one for the +[Discover the JS framework](https://www.odoo.com/documentation/latest/developer/tutorials/discover_js_framework.html) +tutorial's solutions, and one for the +[Master the Odoo web framework](https://www.odoo.com/documentation/lastest/developer/tutorials/master_odoo_web_framework.html) +tutorial's solutions. For example, `17.0`, `17.0-discover-js-framework-solutions` and +`17.0-master-odoo-web-framework-solutions`. From 4c650f360a36fd3f64edddec4caa867799704213 Mon Sep 17 00:00:00 2001 From: "Florian(flg)" Date: Wed, 20 Nov 2024 08:07:03 +0000 Subject: [PATCH 3/4] [FIX] README.md: Fixing typos There are 2 typos in the README.md that lead to broken links. closes odoo/tutorials#196 X-original-commit: 460af3fa62388bf4d118b0dc7ec1bad9697cf02a Signed-off-by: Antoine Vandevenne (anv) --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c80c29b24c8..a0158d919ee 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ # Odoo tutorials This repository hosts the code for the bases of the modules used in the -[official Odoo tutorials](https://www.odoo.com/documentation/lastest/developer/tutorials.html). +[official Odoo tutorials](https://www.odoo.com/documentation/latest/developer/tutorials.html). It has 3 branches for each Odoo version: one for the bases, one for the [Discover the JS framework](https://www.odoo.com/documentation/latest/developer/tutorials/discover_js_framework.html) tutorial's solutions, and one for the -[Master the Odoo web framework](https://www.odoo.com/documentation/lastest/developer/tutorials/master_odoo_web_framework.html) +[Master the Odoo web framework](https://www.odoo.com/documentation/latest/developer/tutorials/master_odoo_web_framework.html) tutorial's solutions. For example, `17.0`, `17.0-discover-js-framework-solutions` and `17.0-master-odoo-web-framework-solutions`. From ecb43aeccef54833aacc20937437d256bd43fb32 Mon Sep 17 00:00:00 2001 From: Garvish Panchal Date: Mon, 28 Apr 2025 16:16:34 +0530 Subject: [PATCH 4/4] Add dynamic content snippet --- .vscode/settings.json | 3 + website_dynamic_snippet/__init__.py | 1 + website_dynamic_snippet/__manifest__.py | 23 ++++++ .../s_dynamic_sale_order_snippet/000.js | 79 +++++++++++++++++++ .../s_dynamic_sale_order_snippet/000.xml | 59 ++++++++++++++ .../s_dynamic_sale_order_snippet/options.js | 28 +++++++ .../tests/tours/dynamic_snippet_tour.js | 58 ++++++++++++++ website_dynamic_snippet/tests/__init__.py | 1 + .../tests/test_dynamic_snippet_tour.py | 6 ++ .../views/snippets/snippets.xml | 41 ++++++++++ 10 files changed, 299 insertions(+) create mode 100644 .vscode/settings.json create mode 100644 website_dynamic_snippet/__init__.py create mode 100644 website_dynamic_snippet/__manifest__.py create mode 100644 website_dynamic_snippet/static/src/snippets/s_dynamic_sale_order_snippet/000.js create mode 100644 website_dynamic_snippet/static/src/snippets/s_dynamic_sale_order_snippet/000.xml create mode 100644 website_dynamic_snippet/static/src/snippets/s_dynamic_sale_order_snippet/options.js create mode 100644 website_dynamic_snippet/static/tests/tours/dynamic_snippet_tour.js create mode 100644 website_dynamic_snippet/tests/__init__.py create mode 100644 website_dynamic_snippet/tests/test_dynamic_snippet_tour.py create mode 100644 website_dynamic_snippet/views/snippets/snippets.xml diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000000..277f7c9898f --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "python.languageServer": "None" +} diff --git a/website_dynamic_snippet/__init__.py b/website_dynamic_snippet/__init__.py new file mode 100644 index 00000000000..e686e4a7a3e --- /dev/null +++ b/website_dynamic_snippet/__init__.py @@ -0,0 +1 @@ +from . import tests diff --git a/website_dynamic_snippet/__manifest__.py b/website_dynamic_snippet/__manifest__.py new file mode 100644 index 00000000000..d0d054f3974 --- /dev/null +++ b/website_dynamic_snippet/__manifest__.py @@ -0,0 +1,23 @@ +{ + 'name': 'Website Dynamic Snippet', + 'version': '18.4.1.0.0', + 'category': 'Website', + 'depends': ['website_sale'], + 'data': [ + 'views/snippets/snippets.xml', + ], + 'assets': { + 'web.assets_frontend': [ + 'website_dynamic_snippet/static/src/snippets/s_dynamic_sale_order_snippet/000.xml', + 'website_dynamic_snippet/static/src/snippets/s_dynamic_sale_order_snippet/000.js', + ], + 'website.assets_wysiwyg': [ + 'website_dynamic_snippet/static/src/snippets/s_dynamic_sale_order_snippet/options.js', + ], + 'web.assets_tests': [ + 'website_dynamic_snippet/static/tests/tours/dynamic_snippet_tour.js', + ], + }, + 'installable': True, + 'application': True, +} diff --git a/website_dynamic_snippet/static/src/snippets/s_dynamic_sale_order_snippet/000.js b/website_dynamic_snippet/static/src/snippets/s_dynamic_sale_order_snippet/000.js new file mode 100644 index 00000000000..b5df4367f37 --- /dev/null +++ b/website_dynamic_snippet/static/src/snippets/s_dynamic_sale_order_snippet/000.js @@ -0,0 +1,79 @@ +/** @odoo-module **/ +import { renderToElement } from "@web/core/utils/render"; +import { Interaction } from "@web/public/interaction"; +import { registry } from "@web/core/registry"; + +class SaleOrderSnippet extends Interaction { + static selector = ".categories_section"; + dynamicContent = { + ".load-more-button": { + "t-on-click": this._onLoadMoreClick, + } + }; + + setup() { + this.orm = this.services.orm; + this.layout = this.el.dataset.setLayout === 'list' ? 'list' : 'grid'; + this.offset = 0; + this.limit = this.layout === 'list' ? 10 : 9; + }; + + async willStart() { + await this.loadCategories(); + }; + + async loadCategories() { + const template = this.layout === 'list' + ? 'website_dynamic_snippet.sale_order_snippet_list' + : 'website_dynamic_snippet.sale_order_snippet_grid'; + + const domain = this.el.dataset.confirmOrderOnly === 'true' ? [['state', '=', 'sale']] : []; + const result = await this.orm.searchRead( + 'sale.order', + domain, + ['id', 'name', 'partner_id', 'amount_total', 'state'], + { + offset: this.offset, + limit: this.limit, + order: 'id ASC', + } + ); + if (result && result.length) { + const content = await renderToElement( + template, + { result: result }, + ); + const selector = this.layout === 'list' ? '.list_sale_order > tbody' : '.card_sale_order'; + const targetContainer = this.el.querySelector(selector); + const newContentContainer = content.querySelector(selector); + + if (this.offset === 0) { + this.el.replaceChildren(content); + } else if (targetContainer && newContentContainer) { + targetContainer.append(...newContentContainer.children); + } + + this.offset += result.length; + } else { + const loadMoreButton = this.el.querySelector('.load-more-button'); + if (loadMoreButton) { + loadMoreButton.style.display = 'none'; + } + } + }; + + async _onLoadMoreClick(ev) { + ev.preventDefault(); + await this.loadCategories(); + }; +}; + +registry + .category("public.interactions") + .add("s_dynamic_sale_order_snippet.get_product_tab", SaleOrderSnippet); +registry + .category("public.interactions.edit") + .add("s_dynamic_sale_order_snippet.get_product_tab", + { + Interaction : SaleOrderSnippet + }); diff --git a/website_dynamic_snippet/static/src/snippets/s_dynamic_sale_order_snippet/000.xml b/website_dynamic_snippet/static/src/snippets/s_dynamic_sale_order_snippet/000.xml new file mode 100644 index 00000000000..bf563516b5d --- /dev/null +++ b/website_dynamic_snippet/static/src/snippets/s_dynamic_sale_order_snippet/000.xml @@ -0,0 +1,59 @@ + + + +
+

Sale Order Details

+
+ + + + + + + + + + + + + + + + + +
NumberCustomer NameStatus
+
+ +
+
+
+
+ + +
+

Sale Order Details

+
+
+ +
+
+
+
Order #
+

Customer:

+

Status:

+
+
+
+
+
+
+ +
+
+
+
+
diff --git a/website_dynamic_snippet/static/src/snippets/s_dynamic_sale_order_snippet/options.js b/website_dynamic_snippet/static/src/snippets/s_dynamic_sale_order_snippet/options.js new file mode 100644 index 00000000000..b20cc34ac74 --- /dev/null +++ b/website_dynamic_snippet/static/src/snippets/s_dynamic_sale_order_snippet/options.js @@ -0,0 +1,28 @@ +import options from "@web_editor/js/editor/snippets.options"; + +options.registry.DynamicSnippetOptions = options.Class.extend({ + confirmOrderOnly(previewMode, widgetValue) { + this.$target[0].dataset.confirmOrderOnly = widgetValue; + }, + + setLayout(previewMode, widgetValue) { + this.$target[0].setAttribute("data-set-layout", widgetValue); + }, + + //-------------------------------------------------------------------------- + // Private + //-------------------------------------------------------------------------- + + /** + * @override + */ + _computeWidgetState(methodName, params) { + if (methodName === "confirmOrderOnly") { + return this.$target[0].dataset.confirmOrderOnly; + } + if (methodName === "setLayout") { + return this.$target[0].getAttribute("data-set-layout"); + } + return this._super(...arguments); + }, +}); diff --git a/website_dynamic_snippet/static/tests/tours/dynamic_snippet_tour.js b/website_dynamic_snippet/static/tests/tours/dynamic_snippet_tour.js new file mode 100644 index 00000000000..70bab2e8127 --- /dev/null +++ b/website_dynamic_snippet/static/tests/tours/dynamic_snippet_tour.js @@ -0,0 +1,58 @@ +import { + clickOnSnippet, + registerWebsitePreviewTour, +} from '@website/js/tours/tour_utils'; + +registerWebsitePreviewTour('website_dynamic_snippet.sale_order_snippet', { + url: '/', + edition: true, +}, + () => { + return [ + { + content: "Drag and drop the sale order snippet", + trigger: "[data-snippet='sale_order_highlight']", + run: "drag_and_drop :iframe #wrap .oe_drop_zone" + }, + ...clickOnSnippet({ id: "categories_section", name:"Sale Order Snippet" }), + { + content: "Click on the layout change Option", + trigger: "[data-name='snippet_data_view']", + run: "click" + }, + { + content: "Change layout to list", + trigger: "[data-set-layout='list']", + run: "click" + }, + { + content: "Check if layout is list", + trigger: ":iframe .categories_section[data-set-layout='list']", + }, + { + content: "Click on the layout change Option", + trigger: "[data-name='snippet_data_view']", + run: "click" + }, + { + content: "Change layout to grid", + trigger: "[data-set-layout='grid']", + run: "click" + }, + { + content: "Check if layout is grid", + trigger: ":iframe .categories_section[data-set-layout='grid']", + }, + { + content: "Click on the confirm order only Option", + trigger: "[data-confirm-order-only='true'] we-checkbox", + run: "click" + }, + { + content: "Save the snippet", + trigger: "[data-action='save']", + run: "click" + }, + ] + } +) diff --git a/website_dynamic_snippet/tests/__init__.py b/website_dynamic_snippet/tests/__init__.py new file mode 100644 index 00000000000..6cb6b56067f --- /dev/null +++ b/website_dynamic_snippet/tests/__init__.py @@ -0,0 +1 @@ +from . import test_dynamic_snippet_tour diff --git a/website_dynamic_snippet/tests/test_dynamic_snippet_tour.py b/website_dynamic_snippet/tests/test_dynamic_snippet_tour.py new file mode 100644 index 00000000000..578f5650df0 --- /dev/null +++ b/website_dynamic_snippet/tests/test_dynamic_snippet_tour.py @@ -0,0 +1,6 @@ +from odoo.tests import HttpCase, tagged + +@tagged('post_install', '-at_install') +class TestDynamicSnippetTour(HttpCase): + def test_dynamic_snippet_tour(self): + self.start_tour("/", "website_dynamic_snippet.sale_order_snippet", login="admin", watch=True) diff --git a/website_dynamic_snippet/views/snippets/snippets.xml b/website_dynamic_snippet/views/snippets/snippets.xml new file mode 100644 index 00000000000..3c6dd260659 --- /dev/null +++ b/website_dynamic_snippet/views/snippets/snippets.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + +