diff --git a/README.md b/README.md index 0c6667bb6f2..a0158d919ee 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/16.0/developer/howtos.html). +This repository hosts the code for the bases of the modules used in the +[official Odoo tutorials](https://www.odoo.com/documentation/latest/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 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/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`. 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..56dc2f779b9 --- /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', + '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..a1cd72893d7 --- /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', + '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..c4fb245621b --- /dev/null +++ b/awesome_dashboard/static/src/dashboard.js @@ -0,0 +1,8 @@ +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..39758f77d89 --- /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', + '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/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..45d06eddc2e --- /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', + '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..0da52b22c9d --- /dev/null +++ b/awesome_kanban/static/src/awesome_kanban_view.js @@ -0,0 +1 @@ +// 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..e8ac1cda552 --- /dev/null +++ b/awesome_owl/__manifest__.py @@ -0,0 +1,41 @@ +# -*- 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', + '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', + ('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..1aaea902b55 --- /dev/null +++ b/awesome_owl/static/src/main.js @@ -0,0 +1,12 @@ +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..4ac769b0aa5 --- /dev/null +++ b/awesome_owl/static/src/playground.js @@ -0,0 +1,5 @@ +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 @@ + + + + + diff --git a/website_airproof/README.md b/website_airproof/README.md new file mode 100644 index 00000000000..6c6390b9424 --- /dev/null +++ b/website_airproof/README.md @@ -0,0 +1,18 @@ +# Odoo Tutorial : Build a website theme + +This branch contains the code necessary for the creation of the website for our Airproof example. +Example used to illustrate the exercises given in the Odoo tutorial: Build a website theme. + +Here is the final design of the 4 pages of Airproof that will be created throughout this tutorial. + +**Home** +![Airproof home page](airproof-home-page.jpg) + +**Contact page** +![Airproof contact page](airproof-contact-page.jpg) + +**Shop page** +![Airproof shop page](airproof-shop-page.jpg) + +**Product page** +![Airproof product page](airproof-product-page.jpg) diff --git a/website_airproof/__init__.py b/website_airproof/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/website_airproof/__manifest__.py b/website_airproof/__manifest__.py new file mode 100644 index 00000000000..439d09e6b72 --- /dev/null +++ b/website_airproof/__manifest__.py @@ -0,0 +1,49 @@ +{ + 'name': 'Airproof Theme', + 'description': 'Airproof Theme - Drones, modelling, camera', + 'category': 'Website/Theme', + # 'version': '18.0.1.0', + 'author': 'PSBE Designers', + 'license': 'LGPL-3', + 'depends': ['website_sale', 'website_sale_wishlist', 'website_blog', 'website_mass_mailing'], + 'data': [ + # Options + 'data/presets.xml', + # Menu + 'data/menu.xml', + # Shapes + 'data/shapes.xml', + # Pages + 'data/pages/home.xml', + 'data/pages/contact.xml', + # Frontend + 'views/website_templates.xml', + 'views/website_sale_templates.xml', + 'views/website_sale_wishlist_templates.xml', + # Snippets + 'views/snippets/options.xml', + 'views/snippets/s_airproof_carousel.xml', + # Images + 'data/images.xml', + ], + 'assets': { + 'web._assets_primary_variables': [ + 'website_airproof/static/src/scss/primary_variables.scss', + ], + 'web._assets_frontend_helpers': [ + ('prepend', 'website_airproof/static/src/scss/bootstrap_overridden.scss'), + ], + 'web.assets_frontend': [ + # SCSS + 'website_airproof/static/src/scss/components/mouse_follower.scss', + 'website_airproof/static/src/scss/layout/header.scss', + 'website_airproof/static/src/scss/pages/product_page.scss', + 'website_airproof/static/src/scss/pages/shop.scss', + 'website_airproof/static/src/scss/snippets/caroussel.scss', + 'website_airproof/static/src/scss/snippets/newsletter.scss', + 'website_airproof/static/src/snippets/s_airproof_carousel/000.scss', + # JS + 'website_airproof/static/src/js/mouse_follower.js', + ], + }, +} diff --git a/website_airproof/airproof-contact-page.jpg b/website_airproof/airproof-contact-page.jpg new file mode 100644 index 00000000000..cc1008a28cb Binary files /dev/null and b/website_airproof/airproof-contact-page.jpg differ diff --git a/website_airproof/airproof-home-page.jpg b/website_airproof/airproof-home-page.jpg new file mode 100644 index 00000000000..53eb1d617b2 Binary files /dev/null and b/website_airproof/airproof-home-page.jpg differ diff --git a/website_airproof/airproof-product-page.jpg b/website_airproof/airproof-product-page.jpg new file mode 100644 index 00000000000..bf07f58651a Binary files /dev/null and b/website_airproof/airproof-product-page.jpg differ diff --git a/website_airproof/airproof-shop-page.jpg b/website_airproof/airproof-shop-page.jpg new file mode 100644 index 00000000000..0a6a5d50a44 Binary files /dev/null and b/website_airproof/airproof-shop-page.jpg differ diff --git a/website_airproof/data/images.xml b/website_airproof/data/images.xml new file mode 100644 index 00000000000..08018dc2ccd --- /dev/null +++ b/website_airproof/data/images.xml @@ -0,0 +1,192 @@ + + + + + + + + + + + + + White arrow icon + + ir.ui.view + + + + Glasses icon + + ir.ui.view + + + + 4K icon + + ir.ui.view + + + + Hand with drone icon + + ir.ui.view + + + + Control icon + + ir.ui.view + + + + Shopping icon + + ir.ui.view + + + + Phone icon + + ir.ui.view + + + + Envelop icon + + ir.ui.view + + + + Arrow icon + + ir.ui.view + + + + Small arrow icon + + ir.ui.view + + + + Check icon + + ir.ui.view + + + + Black Phone icon + + ir.ui.view + + + + Black Envelop icon + + ir.ui.view + + + + + + Drone Airproof Mini + + ir.ui.view + + + + Drone Airproof Pro + + ir.ui.view + + + + Drone Airproof Robin + + ir.ui.view + + + + Drone Airproof Falcon + + ir.ui.view + + + + Drone Airproof Eagle + + ir.ui.view + + + + + + + Drone accessories picture + + ir.ui.view + + + + Drone Robin picture + + ir.ui.view + + + + Drone school picture + + ir.ui.view + + + + Drone flying picture + + ir.ui.view + + + + + + Fields topview + + ir.ui.view + + + + + + Highway topview + + ir.ui.view + + + + + + Drone with blue background picture + + ir.ui.view + + + + + + Sticker logo + + ir.ui.view + + + + Drone picture + + ir.ui.view + + + diff --git a/website_airproof/data/menu.xml b/website_airproof/data/menu.xml new file mode 100644 index 00000000000..ee0a9319f19 --- /dev/null +++ b/website_airproof/data/menu.xml @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + Waterproof drones + + 1 + 10 + +
+ +
+
+
+ + + + About us + /about-us + 1 + + 20 + + + + + Blog + + 1 + 30 + + + Our latest news + /blog/our-latest-news-2 + 1 + + 31 + + + Tutorials + /blog/tutorials-3 + 1 + + 32 + + + + + Contact us + /contactus + 1 + + 40 + +
diff --git a/website_airproof/data/pages/contact.xml b/website_airproof/data/pages/contact.xml new file mode 100644 index 00000000000..f6a4502dc75 --- /dev/null +++ b/website_airproof/data/pages/contact.xml @@ -0,0 +1,156 @@ + + + + + + + + + Contact us + + website_airproof.page_contact + /contactus + + qweb + + + + + Contact us + + + +