├── .gitignore
├── custom-addons
└── owl
│ ├── __init__.py
│ ├── __manifest__.py
│ ├── controllers
│ ├── __init__.py
│ ├── res_partner.py
│ └── simple_mail_service.py
│ ├── models
│ ├── __init__.py
│ ├── product_product.py
│ ├── res_parnter.py
│ └── todo_list.py
│ ├── security
│ └── ir.model.access.csv
│ ├── static
│ └── src
│ │ ├── components
│ │ ├── dashboard
│ │ │ ├── basic_services.js
│ │ │ ├── dashboard.js
│ │ │ ├── dashboard.xml
│ │ │ └── dashboard_services.js
│ │ ├── range_field
│ │ │ ├── range_field.js
│ │ │ └── range_field.xml
│ │ ├── services
│ │ │ ├── odoo_services.js
│ │ │ └── odoo_services.xml
│ │ ├── simple_mail_service
│ │ │ ├── simple_mail.xml
│ │ │ ├── simple_mail_container.js
│ │ │ ├── simple_mail_service.js
│ │ │ └── simple_mail_services.scss
│ │ ├── todo_list
│ │ │ ├── todo_list.js
│ │ │ ├── todo_list.scss
│ │ │ └── todo_list.xml
│ │ ├── username_field
│ │ │ ├── username_field.js
│ │ │ ├── username_field.scss
│ │ │ └── username_field.xml
│ │ ├── valid_email_field
│ │ │ ├── valid_email_field.js
│ │ │ └── valid_email_field.xml
│ │ └── veiw_inheritance
│ │ │ ├── res_parnter_kanban_view.js
│ │ │ ├── res_partner_form_view.js
│ │ │ ├── res_partner_form_view.xml
│ │ │ ├── res_partner_kanban_view.scss
│ │ │ ├── res_partner_kanban_view.xml
│ │ │ ├── res_partner_list_view.js
│ │ │ └── res_partner_list_view.xml
│ │ ├── img
│ │ └── ajscript-media-logo.png
│ │ └── pos
│ │ ├── chrome.xml
│ │ ├── favorite_products
│ │ ├── favorite_products.js
│ │ ├── favorite_products.scss
│ │ └── favorite_products.xml
│ │ ├── favorite_screen
│ │ ├── buttons
│ │ │ ├── favorite_screen_button
│ │ │ │ ├── favorite_screen_button.js
│ │ │ │ └── favorite_screen_button.xml
│ │ │ └── message_popup_button
│ │ │ │ ├── message_popup_button.js
│ │ │ │ └── message_popup_button.xml
│ │ ├── favorite_screen.js
│ │ ├── favorite_screen.scss
│ │ └── favorite_screen.xml
│ │ ├── payment_screen
│ │ ├── payment_screen.js
│ │ └── payment_screen.xml
│ │ ├── popup
│ │ ├── message_popup.js
│ │ └── message_popup.xml
│ │ ├── pos.scss
│ │ └── pos_global_state.js
│ └── views
│ ├── odoo_services.xml
│ ├── res_partner.xml
│ └── todo_list.xml
└── odoo.conf
/.gitignore:
--------------------------------------------------------------------------------
1 | # sphinx build directories
2 | _build/
3 |
4 | # dotfiles
5 | .*
6 | !.gitignore
7 | !.github
8 | !.mailmap
9 | # compiled python files
10 | *.py[co]
11 | __pycache__/
12 | # setup.py egg_info
13 | *.egg-info
14 | # emacs backup files
15 | *~
16 | # hg stuff
17 | *.orig
18 | status
19 | # odoo filestore
20 | odoo/filestore
21 | # maintenance migration scripts
22 | odoo/addons/base/maintenance
23 |
24 | # generated for windows installer?
25 | install/win32/*.bat
26 | install/win32/meta.py
27 |
28 | # needed only when building for win32
29 | setup/win32/static/less/
30 | setup/win32/static/wkhtmltopdf/
31 | setup/win32/static/postgresql*.exe
32 |
33 | # js tooling
34 | node_modules
35 | jsconfig.json
36 | tsconfig.json
37 | package-lock.json
38 | package.json
39 | .husky
40 |
41 | # various virtualenv
42 | /bin/
43 | /build/
44 | /dist/
45 | /include/
46 | /lib/
47 | /man/
48 | /share/
49 | /src/
50 |
--------------------------------------------------------------------------------
/custom-addons/owl/__init__.py:
--------------------------------------------------------------------------------
1 | from . import models
2 | from . import controllers
3 |
--------------------------------------------------------------------------------
/custom-addons/owl/__manifest__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | {
3 | 'name' : 'OWL Tutorial',
4 | 'version' : '1.0',
5 | 'summary': 'OWL Tutorial',
6 | 'sequence': -1,
7 | 'description': """OWL Tutorial""",
8 | 'category': 'OWL',
9 | 'depends' : ['base', 'web', 'point_of_sale'],
10 | 'data': [
11 | 'security/ir.model.access.csv',
12 | 'views/todo_list.xml',
13 | 'views/res_partner.xml',
14 | 'views/odoo_services.xml',
15 | ],
16 | 'demo': [
17 | ],
18 | 'installable': True,
19 | 'application': True,
20 | 'assets': {
21 | 'web.assets_backend': [
22 | 'owl/static/src/components/*/*.js',
23 | 'owl/static/src/components/*/*.xml',
24 | 'owl/static/src/components/*/*.scss',
25 | ],
26 | 'point_of_sale.assets': [
27 | 'owl/static/src/pos/**/*.js',
28 | 'owl/static/src/pos/**/*.xml',
29 | 'owl/static/src/pos/**/*.scss',
30 | ]
31 | },
32 | }
--------------------------------------------------------------------------------
/custom-addons/owl/controllers/__init__.py:
--------------------------------------------------------------------------------
1 | from . import res_partner
2 | from . import simple_mail_service
3 |
--------------------------------------------------------------------------------
/custom-addons/owl/controllers/res_partner.py:
--------------------------------------------------------------------------------
1 | from odoo import http
2 |
3 |
4 | class ResPartner(http.Controller):
5 | @http.route('/owl/rpc_service', type='json', auth='user')
6 | def get_customers(self, limit):
7 | return http.request.env['res.partner'].search_read([], ['name', 'email'], limit=limit)
8 |
9 | @http.route('/owl/dashboard_service', type='json', auth='user')
10 | def dashboard_service(self):
11 | partner = http.request.env['res.partner']
12 | return {
13 | "partners": partner.search_count([]),
14 | "customers": partner.search_count([('is_company', '=', True)]),
15 | "individuals": partner.search_count([('is_company', '=', False)]),
16 | "locations": len(partner.read_group([], ['state_id'], ['state_id'])),
17 | }
18 |
--------------------------------------------------------------------------------
/custom-addons/owl/controllers/simple_mail_service.py:
--------------------------------------------------------------------------------
1 | from odoo import http
2 |
3 |
4 | class SimpleMailService(http.Controller):
5 | @http.route('/owl/simple_mail', type='json', auth='user')
6 | def send_simple_mail(self, **mail_data):
7 | mail = http.request.env['mail.mail']
8 | new_email = mail.create({
9 | 'email_from': mail_data['email_from'],
10 | 'email_to': mail_data['email_to'],
11 | 'subject': mail_data['subject'],
12 | 'body_html': mail_data['message'],
13 | }).send()
14 |
15 | if not new_email:
16 | return False
17 |
18 | return True
19 |
--------------------------------------------------------------------------------
/custom-addons/owl/models/__init__.py:
--------------------------------------------------------------------------------
1 | from . import todo_list
2 | from . import res_parnter
3 | from . import product_product
4 |
--------------------------------------------------------------------------------
/custom-addons/owl/models/product_product.py:
--------------------------------------------------------------------------------
1 | from odoo import models
2 |
3 |
4 | class ProductProduct(models.Model):
5 | _inherit = 'product.product'
6 |
7 | def getFavoriteProducts(self):
8 | products = self.search([('available_in_pos', '=', True), ('product_tag_ids.name', '=', 'Favorite')])
9 | return products.ids
10 |
11 | def mark_favorite(self):
12 | print("self ==>", self)
13 | tags = self.env['product.tag'].search([('name', '=', 'Favorite')], limit=1)
14 |
15 | self.product_tag_ids = [(4, tags.id)]
16 |
17 | def mark_not_favorite(self):
18 | print("self ==>", self)
19 | tags = self.env['product.tag'].search([('name', '=', 'Favorite')], limit=1)
20 |
21 | self.product_tag_ids = [(3, tags.id)]
22 |
--------------------------------------------------------------------------------
/custom-addons/owl/models/res_parnter.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | from odoo import api, fields, models
4 |
5 |
6 | class ResPartner(models.Model):
7 | _inherit = 'res.partner'
8 |
9 | username = fields.Char()
10 | expected_salary = fields.Integer()
11 |
--------------------------------------------------------------------------------
/custom-addons/owl/models/todo_list.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from odoo import api, fields, models
3 |
4 |
5 | class OwlTodo(models.Model):
6 | _name = 'owl.todo.list'
7 | _description = 'OWL Todo List App'
8 |
9 | name = fields.Char(string="Task Name")
10 | completed = fields.Boolean()
11 | color = fields.Char()
12 |
--------------------------------------------------------------------------------
/custom-addons/owl/security/ir.model.access.csv:
--------------------------------------------------------------------------------
1 | id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
2 | access_owl_todo_list,owl_todo_list,model_owl_todo_list,base.group_user,1,1,1,1
--------------------------------------------------------------------------------
/custom-addons/owl/static/src/components/dashboard/basic_services.js:
--------------------------------------------------------------------------------
1 | /** @odoo-module */
2 |
3 | import { registry } from "@web/core/registry"
4 | const { markup } = owl
5 |
6 | export const basicService = {
7 | start(){
8 |
9 | function normalFunction(){
10 | return "This is a normal function"
11 | }
12 |
13 | const arrowFunction = ()=>{
14 | return "This is an arrow function"
15 | }
16 |
17 | return {
18 | string:"Basic Service",
19 | boolean:true,
20 | integer:1,
21 | float:0.5,
22 | array:[1,2,3],
23 | object:{"key": "value"},
24 | "function": ()=>{
25 | console.log("This function has been called")
26 | return "Service function has been called."
27 | },
28 | normal_function: normalFunction(),
29 | arrow_function: arrowFunction(),
30 | html: markup(""),
31 | }
32 | }
33 | }
34 |
35 | registry.category('services').add("basicService", basicService)
--------------------------------------------------------------------------------
/custom-addons/owl/static/src/components/dashboard/dashboard.js:
--------------------------------------------------------------------------------
1 | /** @odoo-module */
2 |
3 | import { registry } from "@web/core/registry"
4 | import { Layout } from "@web/search/layout"
5 | import { getDefaultConfig } from "@web/views/view"
6 | import { useService } from "@web/core/utils/hooks"
7 |
8 | const { Component, useSubEnv, useState, onWillStart } = owl
9 |
10 | export class OwlDashboard extends Component {
11 | setup(){
12 | console.log("Owl Odoo Dasboard")
13 | this.display = {
14 | controlPanel: {"top-right": false, "bottom-right": false}
15 | }
16 |
17 | useSubEnv({
18 | config: {
19 | ...getDefaultConfig(),
20 | ...this.env.config,
21 | }
22 | })
23 |
24 | this.dashboard_service = useService("owlDashboardService")
25 | console.log(this.dashboard_service)
26 | this.dashboard_data = useState(this.dashboard_service.dashboard_data)
27 | this.simple_mail = useService("simpleMailService")
28 | // this.dashboard_data = useState({})
29 |
30 | // onWillStart(async ()=>{
31 | // this.dashboard_data = await this.dashboard_service.getDashboardData()
32 | // console.log("dashboard data == ", this.dashboard_data)
33 | // })
34 | }
35 |
36 | get owlBasicService(){
37 | const basicService = this.env.services.basicService
38 | return basicService
39 | }
40 |
41 | openSimpleMail(){
42 | this.simple_mail.open()
43 | }
44 | }
45 |
46 | OwlDashboard.template = "owl.Dashboard"
47 | OwlDashboard.components = { Layout }
48 |
49 | registry.category("actions").add("owl.Dashboard", OwlDashboard)
--------------------------------------------------------------------------------
/custom-addons/owl/static/src/components/dashboard/dashboard.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
Basic Services
8 |
9 |
10 | String | |
11 |
12 |
13 | Boolean | |
14 |
15 |
16 | Integer | |
17 |
18 |
19 | Float | |
20 |
21 |
22 | Array | |
23 |
24 |
25 | Object | |
26 |
27 |
28 | Function | |
29 |
30 |
31 | Normal Function | |
32 |
33 |
34 | Arrow Function | |
35 |
36 |
37 | HTML | |
38 |
39 |
40 |
41 |
42 |
Dashboard Service
43 |
54 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
Individuals
72 |
73 |
74 |
75 |
76 |
87 |
88 |
89 |
90 |
Simple Mail Service
91 |
92 |
93 |
94 |
95 |
96 |
--------------------------------------------------------------------------------
/custom-addons/owl/static/src/components/dashboard/dashboard_services.js:
--------------------------------------------------------------------------------
1 | /** @odoo-module */
2 |
3 | import { registry } from "@web/core/registry"
4 | const { reactive } = owl
5 |
6 | export const owlDashboardService = {
7 | dependencies:["rpc"],
8 | async start(env, { rpc }){
9 | let dashboard_data = reactive({})
10 |
11 | Object.assign(dashboard_data, await rpc("/owl/dashboard_service/"))
12 |
13 | // setInterval(async ()=>{
14 | // Object.assign(dashboard_data, await rpc("/owl/dashboard_service/"))
15 | // }, 5000)
16 |
17 | async function getDashboardData(){
18 | return await rpc("/owl/dashboard_service/")
19 | }
20 | return {
21 | dashboard_data,
22 | getDashboardData: getDashboardData,
23 | }
24 | }
25 | }
26 |
27 | registry.category("services").add("owlDashboardService", owlDashboardService)
--------------------------------------------------------------------------------
/custom-addons/owl/static/src/components/range_field/range_field.js:
--------------------------------------------------------------------------------
1 | /** @odoo-module **/
2 |
3 | import { registry } from "@web/core/registry";
4 | import { standardFieldProps } from "@web/views/fields/standard_field_props";
5 |
6 | import { Component, useState, onWillUpdateProps } from "@odoo/owl";
7 |
8 | export class RangeField extends Component {
9 | setup() {
10 | this.state = useState({
11 | range: this.props.value || '',
12 | });
13 |
14 | const { currency_id } = this.props.record.data
15 | this.currency = currency_id ? currency_id[1] : ''
16 | }
17 | }
18 |
19 | RangeField.template = "owl.RangeField";
20 | RangeField.props = {
21 | ...standardFieldProps,
22 | };
23 |
24 | RangeField.supportedTypes = ["integer"];
25 |
26 | registry.category("fields").add("range", RangeField);
27 |
--------------------------------------------------------------------------------
/custom-addons/owl/static/src/components/range_field/range_field.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/custom-addons/owl/static/src/components/services/odoo_services.js:
--------------------------------------------------------------------------------
1 | /** @odoo-module */
2 |
3 | import { registry } from "@web/core/registry"
4 | import { Layout } from "@web/search/layout"
5 | import { getDefaultConfig } from "@web/views/view"
6 | import { useService } from "@web/core/utils/hooks"
7 | import { ConfirmationDialog } from "@web/core/confirmation_dialog/confirmation_dialog"
8 | import { routeToUrl } from "@web/core/browser/router_service"
9 | import { browser } from "@web/core/browser/browser"
10 |
11 | const { Component, useSubEnv, useState } = owl
12 |
13 | export class OwlOdooServices extends Component {
14 | setup(){
15 | console.log("Owl Odoo Services")
16 | this.display = {
17 | controlPanel: {"top-right": false, "bottom-right": false}
18 | }
19 |
20 | useSubEnv({
21 | config: {
22 | ...getDefaultConfig(),
23 | ...this.env.config,
24 | }
25 | })
26 |
27 | this.cookieService = useService("cookie")
28 | console.log(this.cookieService)
29 |
30 | if (this.cookieService.current.dark_theme == undefined){
31 | this.cookieService.setCookie("dark_theme", false)
32 | }
33 |
34 | const router = this.env.services.router
35 |
36 | this.state = useState({
37 | dark_theme: this.cookieService.current.dark_theme,
38 | get_http_data: [],
39 | post_http_data: [],
40 | rpc_data: [],
41 | orm_data: [],
42 | bg_success: router.current.search.bg_success,
43 | user_data: null,
44 | company_data: null,
45 | })
46 |
47 | const titleService = useService("title")
48 | titleService.setParts({zopenerp: "AJScript", odoo: "Media", any:"Tutorials"})
49 | console.log(titleService.getParts())
50 | }
51 |
52 | showNotification(){
53 | const notification = this.env.services.notification
54 | notification.add("This is a sample notification.", {
55 | title: "Odoo Notification Service",
56 | type: "info", //info, warning, danger, success
57 | sticky: true,
58 | className: "p-4",
59 | buttons: [
60 | {
61 | name: "Notification Action",
62 | onClick: ()=>{
63 | console.log("This is notification action")
64 | },
65 | primary: true,
66 | },
67 | {
68 | name: "Show me again",
69 | onClick: ()=>{
70 | this.showNotification()
71 | },
72 | primary: false,
73 | }
74 | ]
75 | })
76 | }
77 |
78 | showDialog(){
79 | const dialog = this.env.services.dialog
80 | dialog.add(ConfirmationDialog, {
81 | title: "Dialog Service",
82 | body: "Are you sure you want to continue this action?",
83 | confirm: ()=>{
84 | console.log("Dialog Confirmed.")
85 | },
86 | cancel: ()=>{
87 | console.log("Dialog Cancelled")
88 | }
89 | }, {
90 | onClose: ()=> {
91 | console.log("Dialog service closed....")
92 | }
93 | })
94 | console.log(dialog)
95 | }
96 |
97 | showEffect(){
98 | const effect = this.env.services.effect
99 | console.log(effect)
100 | effect.add({
101 | type: "rainbow_man",
102 | message: "This is an awesome odoo effect service."
103 | })
104 | }
105 |
106 | setCookieService(){
107 | if (this.cookieService.current.dark_theme == 'false'){
108 | this.cookieService.setCookie("dark_theme", true)
109 | } else {
110 | this.cookieService.setCookie("dark_theme", false)
111 | }
112 |
113 | this.state.dark_theme = this.cookieService.current.dark_theme
114 |
115 | this.cookieService.deleteCookie("test")
116 | }
117 |
118 | async getHttpService(){
119 | const http = this.env.services.http
120 | console.log(http)
121 | const data = await http.get('https://dummyjson.com/products')
122 | console.log(data)
123 | this.state.get_http_data = data.products
124 | }
125 |
126 | async postHttpService(){
127 | const http = this.env.services.http
128 | console.log(http)
129 | const data = await http.post('https://dummyjson.com/products/add', {title: 'BMW Pencil',})
130 | console.log(data)
131 | this.state.post_http_data = data
132 | }
133 |
134 | async getRpcService(){
135 | const rpc = this.env.services.rpc
136 | const data = await rpc("/owl/rpc_service", {limit: 15})
137 | console.log(data)
138 | this.state.rpc_data = data
139 | }
140 |
141 | async getOrmService(){
142 | const orm = this.env.services.orm
143 | const data = await orm.searchRead("res.partner", [], ['name', 'email'])
144 | console.log(data)
145 | this.state.orm_data = data
146 | }
147 |
148 | getActionService(){
149 | const action = this.env.services.action
150 | action.doAction({
151 | type: "ir.actions.act_window",
152 | name: "Action Service",
153 | res_model: "res.partner",
154 | domain:[],
155 | context:{search_default_type_company: 1},
156 | views:[
157 | [false, "list"],
158 | [false, "form"],
159 | [false, "kanban"],
160 | ],
161 | view_mode:"list,form,kanban",
162 | target: "current"
163 | })
164 | }
165 |
166 | getRouterService(){
167 | const router = this.env.services.router
168 | console.log(router)
169 | let { search } = router.current
170 | search.bg_success = search.bg_success == "1" ? "0" : "1"
171 | console.log(router.current)
172 | browser.location.href = browser.location.origin + routeToUrl(router.current)
173 | }
174 |
175 | getUserService(){
176 | const user = this.env.services.user
177 | console.log(user)
178 | this.state.user_data = JSON.stringify(user)
179 | }
180 |
181 | getCompanyService(){
182 | const company = this.env.services.company
183 | console.log(company)
184 | this.state.company_data = JSON.stringify(company)
185 | }
186 | }
187 |
188 | OwlOdooServices.template = "owl.OdooServices"
189 | OwlOdooServices.components = { Layout }
190 |
191 | registry.category("actions").add("owl.OdooServices", OwlOdooServices)
--------------------------------------------------------------------------------
/custom-addons/owl/static/src/components/services/odoo_services.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
31 |
32 |
38 |
39 |
45 |
46 |
52 |
53 |
56 |
57 |
60 |
61 |
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/custom-addons/owl/static/src/components/simple_mail_service/simple_mail.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
Simple Mail Service
8 |
9 |
12 |
13 |
14 |
15 |
18 |
19 |
20 |
21 |
24 |
25 |
26 |
27 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/custom-addons/owl/static/src/components/simple_mail_service/simple_mail_container.js:
--------------------------------------------------------------------------------
1 | /** @odoo-module */
2 |
3 | const { Component, xml, useState } = owl
4 |
5 | export class SimpleMailContainer extends Component {
6 | setup(){
7 | // console.log("This is a simple mail container.", this.props)
8 | this.state = useState(this.props.simple_mail)
9 | }
10 | }
11 |
12 | export class SimpleMail extends Component {
13 | setup(){
14 | console.log("This is simple mail component")
15 | this.state = useState({
16 | email_to: "",
17 | subject: "",
18 | message: "",
19 | })
20 | }
21 | }
22 |
23 | SimpleMail.template = "owl.SimpleMail"
24 |
25 | SimpleMailContainer.template = xml`
26 |
27 |
28 |
29 |
30 |
31 | `
32 |
33 | SimpleMailContainer.components = { SimpleMail }
--------------------------------------------------------------------------------
/custom-addons/owl/static/src/components/simple_mail_service/simple_mail_service.js:
--------------------------------------------------------------------------------
1 | /** @odoo-module */
2 |
3 | import { registry } from "@web/core/registry"
4 | import { SimpleMailContainer } from "./simple_mail_container"
5 | const { reactive } = owl
6 |
7 | export const simpleMailService = {
8 | dependencies:["orm", "user", "rpc","notification"],
9 | async start(env, { orm, user, rpc, notification }){
10 | // console.log("user service", user)
11 | const user_email = await orm.searchRead("res.partner", [["id", "=", user.partnerId]], ["email"])
12 | // console.log("user email", user_email)
13 |
14 | let simple_mail = reactive({
15 | isActive: false,
16 | open,
17 | close,
18 | send,
19 | email_from: user_email[0].email
20 | })
21 |
22 | registry.category("main_components").add("SimpleMailContainer", {
23 | Component: SimpleMailContainer,
24 | props: { simple_mail }
25 | })
26 |
27 | function open(){
28 | simple_mail.isActive = true
29 | }
30 |
31 | function close(){
32 | simple_mail.isActive = false
33 | }
34 |
35 | async function send(mail){
36 | console.log("Send simple mail service", mail)
37 | const data = {
38 | email_from: simple_mail.email_from,
39 | email_to: mail.email_to,
40 | subject: mail.subject,
41 | message: mail.message,
42 | }
43 |
44 | const new_email = await rpc("/owl/simple_mail", data)
45 | console.log(new_email)
46 | if (new_email){
47 | notification.add("Mail successfully sent", {type: "info"})
48 | } else {
49 | notification.add("Oooops! Something went wrong. Mail not sent.", {type: "danger"})
50 | }
51 |
52 | close()
53 | }
54 |
55 | return {
56 | open
57 | }
58 | }
59 | }
60 |
61 | registry.category("services").add("simpleMailService", simpleMailService)
--------------------------------------------------------------------------------
/custom-addons/owl/static/src/components/simple_mail_service/simple_mail_services.scss:
--------------------------------------------------------------------------------
1 | .o_simple_mail {
2 | .o_simple_mail_wrapper {
3 | width: 500px;
4 | height: auto;
5 | }
6 | }
--------------------------------------------------------------------------------
/custom-addons/owl/static/src/components/todo_list/todo_list.js:
--------------------------------------------------------------------------------
1 | /** @odoo-module **/
2 |
3 | import { registry } from '@web/core/registry';
4 | const { Component, useState, onWillStart, useRef } = owl;
5 | import { useService } from "@web/core/utils/hooks";
6 |
7 | export class OwlTodoList extends Component {
8 | setup(){
9 | this.state = useState({
10 | task:{name:"", color:"#FF0000", completed:false},
11 | taskList:[],
12 | isEdit: false,
13 | activeId: false,
14 | })
15 | this.orm = useService("orm")
16 | this.model = "owl.todo.list"
17 | this.searchInput = useRef("search-input")
18 |
19 | onWillStart(async ()=>{
20 | await this.getAllTasks()
21 | })
22 | }
23 |
24 | async getAllTasks(){
25 | this.state.taskList = await this.orm.searchRead(this.model, [], ["name", "color", "completed"])
26 | }
27 |
28 | addTask(){
29 | this.resetForm()
30 | this.state.activeId = false
31 | this.state.isEdit = false
32 | }
33 |
34 | editTask(task){
35 | this.state.activeId = task.id
36 | this.state.isEdit = true
37 | this.state.task = {...task}
38 | }
39 |
40 | async saveTask(){
41 |
42 | if (!this.state.isEdit){
43 | await this.orm.create(this.model, [this.state.task])
44 | this.resetForm()
45 | } else {
46 | await this.orm.write(this.model, [this.state.activeId], this.state.task)
47 | }
48 |
49 | await this.getAllTasks()
50 | }
51 |
52 | resetForm(){
53 | this.state.task = {name:"", color:"#FF0000", completed:false}
54 | }
55 |
56 | async deleteTask(task){
57 | await this.orm.unlink(this.model, [task.id])
58 | await this.getAllTasks()
59 | }
60 |
61 | async searchTasks(){
62 | const text = this.searchInput.el.value
63 | this.state.taskList = await this.orm.searchRead(this.model, [['name','ilike',text]], ["name", "color", "completed"])
64 | }
65 |
66 | async toggleTask(e, task){
67 | await this.orm.write(this.model, [task.id], {completed: e.target.checked})
68 | await this.getAllTasks()
69 | }
70 |
71 | async updateColor(e, task){
72 | await this.orm.write(this.model, [task.id], {color: e.target.value})
73 | await this.getAllTasks()
74 | }
75 | }
76 |
77 | OwlTodoList.template = 'owl.TodoList'
78 | registry.category('actions').add('owl.action_todo_list_js', OwlTodoList);
--------------------------------------------------------------------------------
/custom-addons/owl/static/src/components/todo_list/todo_list.scss:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alferjay/odoo-owl-tutorial/380ac3ee1eb753df6d7aed452732f3b302325a08/custom-addons/owl/static/src/components/todo_list/todo_list.scss
--------------------------------------------------------------------------------
/custom-addons/owl/static/src/components/todo_list/todo_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
85 |
86 |
87 |
88 |
89 |
90 |
--------------------------------------------------------------------------------
/custom-addons/owl/static/src/components/username_field/username_field.js:
--------------------------------------------------------------------------------
1 | /** @odoo-module */
2 |
3 | import { registry } from "@web/core/registry"
4 | import { CharField } from "@web/views/fields/char/char_field"
5 |
6 | class UsernameField extends CharField {
7 | setup(){
8 | super.setup()
9 | console.log("Char Field Inherited")
10 | console.log(this.props)
11 | }
12 |
13 | get emailDomain(){
14 | const { email } = this.props.record.data
15 | return email ? email.split('@')[1] : ''
16 | }
17 | }
18 |
19 | UsernameField.template = "owl.UsernameField"
20 | UsernameField.supportedTypes = ["char"]
21 | UsernameField.components = { CharField }
22 |
23 | registry.category("fields").add("username", UsernameField)
--------------------------------------------------------------------------------
/custom-addons/owl/static/src/components/username_field/username_field.scss:
--------------------------------------------------------------------------------
1 | .o_username_field {
2 | input {
3 | flex: 1
4 | }
5 | }
--------------------------------------------------------------------------------
/custom-addons/owl/static/src/components/username_field/username_field.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | @
7 |
8 |
9 |
--------------------------------------------------------------------------------
/custom-addons/owl/static/src/components/valid_email_field/valid_email_field.js:
--------------------------------------------------------------------------------
1 | /** @odoo-module */
2 |
3 | import { registry } from "@web/core/registry"
4 | import { EmailField } from "@web/views/fields/email/email_field"
5 |
6 | class ValidEmailField extends EmailField {
7 | setup(){
8 | super.setup()
9 | console.log("Email Field Inherited")
10 | console.log(this.props)
11 | }
12 |
13 | get isValidEmail(){
14 | let re = /\S+@\S+\.\S+/;
15 | return re.test(this.props.value)
16 | }
17 | }
18 |
19 | ValidEmailField.template = "owl.ValidEmailField"
20 | ValidEmailField.supportedTypes = ["char"]
21 |
22 | registry.category("fields").add("valid_email", ValidEmailField)
--------------------------------------------------------------------------------
/custom-addons/owl/static/src/components/valid_email_field/valid_email_field.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Invalid Email!
7 |
8 |
9 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/custom-addons/owl/static/src/components/veiw_inheritance/res_parnter_kanban_view.js:
--------------------------------------------------------------------------------
1 | /** @odoo-module */
2 |
3 | import { registry } from "@web/core/registry"
4 | import { kanbanView } from "@web/views/kanban/kanban_view"
5 | import { KanbanController } from "@web/views/kanban/kanban_controller"
6 | import { useService } from "@web/core/utils/hooks"
7 |
8 | const { onWillStart } = owl
9 |
10 | class ResPartnerKanbanController extends KanbanController {
11 | setup(){
12 | super.setup()
13 | console.log("This is res partner kanban controller")
14 | this.action = useService("action")
15 | this.orm = useService("orm")
16 |
17 | onWillStart(async ()=>{
18 | this.customerLocations = await this.orm.readGroup("res.partner", [], ['state_id'], ['state_id'])
19 | console.log(this.customerLocations)
20 | })
21 | }
22 |
23 | openSalesView(){
24 | console.log("Open Sales view")
25 | this.action.doAction({
26 | type: "ir.actions.act_window",
27 | name: "Customer Sales",
28 | res_model: "sale.order",
29 | views: [[false, "list"], [false, "form"]]
30 | })
31 | }
32 |
33 | selectLocations(state){
34 | const id = state[0]
35 | const name = state[1]
36 |
37 | this.env.searchModel.setDomainParts({
38 | state: {
39 | domain: [['state_id', '=', id]],
40 | facetLabel: name
41 | }
42 | })
43 | }
44 | }
45 |
46 | ResPartnerKanbanController.template = "owl.ResPartnerKanbanView"
47 |
48 | export const resPartnerKanbanView = {
49 | ...kanbanView,
50 | Controller: ResPartnerKanbanController,
51 | buttonTemplate: "owl.ResPartnerKanbanView.Buttons",
52 | }
53 |
54 | registry.category("views").add("res_partner_kanban_view", resPartnerKanbanView)
--------------------------------------------------------------------------------
/custom-addons/owl/static/src/components/veiw_inheritance/res_partner_form_view.js:
--------------------------------------------------------------------------------
1 | /** @odoo-module */
2 |
3 | import { registry } from "@web/core/registry"
4 | import { formView } from "@web/views/form/form_view"
5 | import { FormController } from "@web/views/form/form_controller"
6 | import { useService } from "@web/core/utils/hooks"
7 |
8 | class ResPartnerFormController extends FormController {
9 | setup(){
10 | super.setup()
11 | console.log("This is res partner form controller")
12 | this.action = useService("action")
13 | }
14 |
15 | openWebsite(url){
16 | this.action.doAction({
17 | type: "ir.actions.act_url",
18 | target: "self",
19 | url
20 | })
21 | }
22 | }
23 |
24 | ResPartnerFormController.template = "owl.ResPartnerFormView"
25 |
26 | export const resPartnerFormView = {
27 | ...formView,
28 | Controller: ResPartnerFormController,
29 | }
30 |
31 | registry.category("views").add("res_partner_form_view", resPartnerFormView)
--------------------------------------------------------------------------------
/custom-addons/owl/static/src/components/veiw_inheritance/res_partner_form_view.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/custom-addons/owl/static/src/components/veiw_inheritance/res_partner_kanban_view.scss:
--------------------------------------------------------------------------------
1 | .o_res_partner_kanban_view_sidebar {
2 | flex: 0 0 300px;
3 | }
--------------------------------------------------------------------------------
/custom-addons/owl/static/src/components/veiw_inheritance/res_partner_kanban_view.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
22 |
23 |
24 |
25 | model.useSampleModel ? 'o_view_sample_data' : '' + "d-flex"
26 |
27 |
28 |
--------------------------------------------------------------------------------
/custom-addons/owl/static/src/components/veiw_inheritance/res_partner_list_view.js:
--------------------------------------------------------------------------------
1 | /** @odoo-module */
2 |
3 | import { registry } from "@web/core/registry"
4 | import { listView } from "@web/views/list/list_view"
5 | import { ListController } from "@web/views/list/list_controller"
6 | import { useService } from "@web/core/utils/hooks"
7 |
8 | class ResPartnerListController extends ListController {
9 | setup(){
10 | super.setup()
11 | console.log("This is res partner controller")
12 | this.action = useService("action")
13 | }
14 |
15 | openSalesView(){
16 | console.log("Open Sales view")
17 | this.action.doAction({
18 | type: "ir.actions.act_window",
19 | name: "Customer Sales",
20 | res_model: "sale.order",
21 | views: [[false, "list"], [false, "form"]]
22 | })
23 | }
24 | }
25 |
26 | export const resPartnerListView = {
27 | ...listView,
28 | Controller: ResPartnerListController,
29 | buttonTemplate: "owl.ResPartnerListView.Buttons",
30 | }
31 |
32 | registry.category("views").add("res_partner_list_view", resPartnerListView)
--------------------------------------------------------------------------------
/custom-addons/owl/static/src/components/veiw_inheritance/res_partner_list_view.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/custom-addons/owl/static/src/img/ajscript-media-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alferjay/odoo-owl-tutorial/380ac3ee1eb753df6d7aed452732f3b302325a08/custom-addons/owl/static/src/img/ajscript-media-logo.png
--------------------------------------------------------------------------------
/custom-addons/owl/static/src/pos/chrome.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | /owl/static/src/img/ajscript-media-logo.png
7 |
8 |
9 |
--------------------------------------------------------------------------------
/custom-addons/owl/static/src/pos/favorite_products/favorite_products.js:
--------------------------------------------------------------------------------
1 | /** @odoo-module */
2 |
3 | import Registries from "point_of_sale.Registries"
4 | import ProductScreen from "point_of_sale.ProductScreen"
5 | const { onWillStart } = owl
6 |
7 | const ProductScreenInherit = (product_screen) => class extends product_screen {
8 | setup(){
9 | super.setup()
10 | console.log("Product Screen Inherited")
11 | console.log("POS DB", this.env.pos.db)
12 | console.log("POS Services", this.env.services)
13 | this.favorite_products = []
14 |
15 | onWillStart(async ()=>{
16 | // const data = await this.env.services.rpc({
17 | // 'model': 'product.product',
18 | // 'method': 'search',
19 | // 'kwargs': {
20 | // 'domain': [['available_in_pos', '=', true], ['product_tag_ids.name', '=', 'Favorite']]
21 | // }
22 | // })
23 |
24 | // const data = await this.env.services.rpc({
25 | // 'model': 'product.product',
26 | // 'method': 'getFavoriteProducts',
27 | // 'args': [{}]
28 | // })
29 |
30 | // this.favorite_products = data
31 | this.favorite_products = await this.env.pos.favorite_products
32 | // console.log("RPC Data", data)
33 | })
34 | }
35 |
36 | get favoriteProducts(){
37 | // let products = this.env.pos.db.get_product_by_category(4);
38 | let products = this.env.pos.db.product_by_id;
39 | console.log("Products", products)
40 | let favorites = []
41 | this.favorite_products.forEach(p => favorites.push(products[p]))
42 | return favorites
43 | }
44 | }
45 |
46 | Registries.Component.extend(ProductScreen, ProductScreenInherit)
--------------------------------------------------------------------------------
/custom-addons/owl/static/src/pos/favorite_products/favorite_products.scss:
--------------------------------------------------------------------------------
1 | .favorite-products-container {
2 | background: #ccc;
3 | padding: 10px;
4 | min-height: 200px;
5 | }
6 |
7 | .favorite-products {
8 | display: flex;
9 | flex-wrap: wrap;
10 |
11 | .product {
12 | background: #ccc;
13 | padding: 3px;
14 | flex-shrink: 1;
15 | flex-grow: 0;
16 | flex-basis: 80px;
17 | }
18 | }
--------------------------------------------------------------------------------
/custom-addons/owl/static/src/pos/favorite_products/favorite_products.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/custom-addons/owl/static/src/pos/favorite_screen/buttons/favorite_screen_button/favorite_screen_button.js:
--------------------------------------------------------------------------------
1 | odoo.define('point_of_sale.FavoriteScreenButton', function(require) {
2 | 'use strict';
3 |
4 | const PosComponent = require('point_of_sale.PosComponent');
5 | const ProductScreen = require('point_of_sale.ProductScreen');
6 | const Registries = require('point_of_sale.Registries');
7 |
8 | class FavoriteScreenButton extends PosComponent {
9 | setup() {
10 | super.setup();
11 | console.log("New Favorite Screen Button")
12 | }
13 |
14 | showFavoriteProduct(){
15 | this.showScreen('FavoriteProductScreen')
16 | }
17 | }
18 | FavoriteScreenButton.template = 'FavoriteScreenButton';
19 |
20 | ProductScreen.addControlButton({
21 | component: FavoriteScreenButton,
22 | position: ['after', 'OrderlineCustomerNoteButton'],
23 | condition: function(){
24 | //this.rpc
25 | //this.env.pos
26 | return true
27 | }
28 | });
29 |
30 | Registries.Component.add(FavoriteScreenButton);
31 |
32 | return FavoriteScreenButton;
33 | });
34 |
--------------------------------------------------------------------------------
/custom-addons/owl/static/src/pos/favorite_screen/buttons/favorite_screen_button/favorite_screen_button.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Favorites
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/custom-addons/owl/static/src/pos/favorite_screen/buttons/message_popup_button/message_popup_button.js:
--------------------------------------------------------------------------------
1 | odoo.define('point_of_sale.MessagePopupButton', function(require) {
2 | 'use strict';
3 |
4 | const PosComponent = require('point_of_sale.PosComponent');
5 | const ProductScreen = require('point_of_sale.ProductScreen');
6 | const Registries = require('point_of_sale.Registries');
7 |
8 | class MessagePopupButton extends PosComponent {
9 | setup() {
10 | super.setup();
11 | }
12 |
13 | async showMessagePopup(){
14 | const { confirmed, payload } = await this.showPopup('MessagePopup')
15 | console.log("confirmed payload ==>", confirmed, payload)
16 |
17 | if (confirmed){
18 | this.env.pos.popupMessage = payload
19 | }
20 | }
21 | }
22 | MessagePopupButton.template = 'MessagePopupButton';
23 |
24 | Registries.Component.add(MessagePopupButton);
25 |
26 | return MessagePopupButton;
27 | });
28 |
--------------------------------------------------------------------------------
/custom-addons/owl/static/src/pos/favorite_screen/buttons/message_popup_button/message_popup_button.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Popup Message
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/custom-addons/owl/static/src/pos/favorite_screen/favorite_screen.js:
--------------------------------------------------------------------------------
1 | odoo.define('point_of_sale.FavoriteProductScreen', function (require){
2 | 'use strict';
3 |
4 | const Registries = require('point_of_sale.Registries');
5 | const PosComponent = require('point_of_sale.PosComponent');
6 | const { useState, onWillStart } = owl;
7 |
8 | class FavoriteProductScreen extends PosComponent {
9 | setup(){
10 | super.setup()
11 | console.log("New Favorite Product Screen")
12 | this.state = useState({
13 | activeProduct: {},
14 | isFavorite: true,
15 | favorite_products: [],
16 | products: [],
17 | })
18 | this.date = new Date().toUTCString();
19 |
20 | onWillStart(async ()=>{
21 | this.state.favorite_products = await this.env.pos.favorite_products
22 | this.getProducts()
23 | })
24 | }
25 |
26 | getProducts(){
27 | let products = this.env.pos.db.product_by_id;
28 | let product_list = []
29 | console.log("products ==>", Object.entries(products))
30 |
31 | if (this.state.isFavorite){
32 | this.state.favorite_products.forEach(p => product_list.push(products[p]))
33 | } else {
34 | Object.entries(products).forEach(p => product_list.push(p[1]))
35 | }
36 |
37 | this.state.isFavorite = !this.state.isFavorite
38 | this.state.products = product_list
39 | }
40 |
41 | setActiveProduct(product){
42 | this.state.activeProduct = product;
43 | }
44 |
45 | async markFavorite(product){
46 | await this.rpc({
47 | model: 'product.product',
48 | method: 'mark_favorite',
49 | args: [[product.id]]
50 | })
51 |
52 | await this.env.pos.setFavoriteProducts()
53 | this.state.favorite_products = await this.env.pos.favorite_products
54 | this.getProducts()
55 | }
56 |
57 | async markNotFavorite(product){
58 | await this.rpc({
59 | model: 'product.product',
60 | method: 'mark_not_favorite',
61 | args: [[product.id]]
62 | })
63 |
64 | await this.env.pos.setFavoriteProducts()
65 | this.state.favorite_products = await this.env.pos.favorite_products
66 | this.getProducts()
67 | }
68 | }
69 |
70 | FavoriteProductScreen.template = 'FavoriteProductScreen';
71 | Registries.Component.add(FavoriteProductScreen)
72 |
73 | return FavoriteProductScreen
74 | })
--------------------------------------------------------------------------------
/custom-addons/owl/static/src/pos/favorite_screen/favorite_screen.scss:
--------------------------------------------------------------------------------
1 | .favorite-product-screen {
2 | background-color: #011801!important;
3 | color: white;
4 | display: flex;
5 | flex-direction: column;
6 | height: 100%;
7 |
8 | .screen-header {
9 | min-height: 100px;
10 | display: flex;
11 | justify-content: space-between;
12 | padding: 10px;
13 |
14 | .large-buttons {
15 | display: flex;
16 |
17 | button {
18 | width: 150px;
19 | height: 100px;
20 | font-size: medium;
21 | margin-right: 10px;
22 | font-weight: bold;
23 |
24 | &.red {
25 | background-color: red;
26 | color: white;
27 | }
28 | &.orange {
29 | background-color: orange;
30 | color: white;
31 | }
32 | &.blue {
33 | background-color: blue;
34 | color: white;
35 | }
36 | }
37 | }
38 | }
39 |
40 | .favorite-content {
41 | display: flex;
42 | height:100%;
43 | overflow: hidden;
44 | }
45 |
46 | .left-pane {
47 | flex: 1 1 70%;
48 | overflow: auto;
49 | padding: 10px;
50 |
51 | .favorite-list {
52 | width: 100%;
53 | background-color: white;
54 | color: black;
55 |
56 | tr, td, th {
57 | padding: 10px;
58 | }
59 |
60 | tr {
61 | border: 1px solid #eee;
62 | cursor: pointer;
63 |
64 | &:nth-child(even){
65 | background-color: #ccc;
66 | }
67 |
68 | &:hover {
69 | background-color: #017e84;
70 | color: white;
71 | }
72 | }
73 | }
74 | }
75 |
76 | .right-pane {
77 | flex: 1 1 30%;
78 | display: flex;
79 | flex-direction: column;
80 | height: 100%;
81 | background-color: #333;
82 |
83 | .selected-product {
84 | padding: 10px;
85 | }
86 |
87 | .pads {
88 | margin-top: auto;
89 |
90 | .control-button {
91 | color: #333;
92 | }
93 |
94 | .subpads {
95 | display: flex;
96 | }
97 | }
98 | }
99 | }
--------------------------------------------------------------------------------
/custom-addons/owl/static/src/pos/favorite_screen/favorite_screen.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
19 |
20 |
21 |
22 |
23 |
24 | Product Name |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 | []
33 |
34 |
35 | |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
Product Details
44 |
45 | Name:
46 | Code:
47 | Price:
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
Custom Action
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/custom-addons/owl/static/src/pos/payment_screen/payment_screen.js:
--------------------------------------------------------------------------------
1 | /** @odoo-module */
2 |
3 | import Registries from "point_of_sale.Registries"
4 | import PaymentScreen from "point_of_sale.PaymentScreen"
5 |
6 | const PaymentScreenInherit = (payment_screen) => class extends payment_screen {
7 | setup(){
8 | super.setup()
9 | console.log("Inherited Payment Screen")
10 | }
11 |
12 | addNewPaymentLine({ detail: paymentMethod }) {
13 | const payment_line = super.addNewPaymentLine({ detail: paymentMethod })
14 | console.log("Inherited add new payment line")
15 | return payment_line
16 | }
17 |
18 | go_next(){
19 | console.log("You clicked next from payment screen.")
20 | }
21 | }
22 |
23 | Registries.Component.extend(PaymentScreen, PaymentScreenInherit)
--------------------------------------------------------------------------------
/custom-addons/owl/static/src/pos/payment_screen/payment_screen.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
8 | Next
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/custom-addons/owl/static/src/pos/popup/message_popup.js:
--------------------------------------------------------------------------------
1 | odoo.define('point_of_sale.MessagePopup', function (require){
2 | 'use strict';
3 |
4 | const Registries = require('point_of_sale.Registries');
5 | const AbstractAwaitablePopup = require('point_of_sale.AbstractAwaitablePopup');
6 | const { useState, useRef, onMounted } = owl;
7 |
8 | class MessagePopup extends AbstractAwaitablePopup {
9 | setup(){
10 | super.setup()
11 | console.log("New Message Popup")
12 | this.state = useState({text_value: ''})
13 | this.txtRef = useRef('text-value')
14 |
15 | onMounted(()=>this.txtRef.el.focus())
16 | }
17 |
18 | confirm(){
19 | console.log("You confirmed message popup.")
20 | console.log("Text Value", this.state.text_value)
21 | super.confirm()
22 | }
23 |
24 | cancel(){
25 | console.log("You cancelled message popup.")
26 | super.cancel()
27 | }
28 |
29 | getPayload(){
30 | return this.state.text_value;
31 | }
32 | }
33 |
34 | MessagePopup.template = 'MessagePopup';
35 | Registries.Component.add(MessagePopup)
36 |
37 | return MessagePopup
38 | })
--------------------------------------------------------------------------------
/custom-addons/owl/static/src/pos/popup/message_popup.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/custom-addons/owl/static/src/pos/pos.scss:
--------------------------------------------------------------------------------
1 | .pos .pos-logo {
2 | height: 80%;
3 | }
4 |
5 | .pos .pos-topheader {
6 | background: #011801;
7 | }
8 |
9 | .pos .rightpane {
10 | background: white;
11 | }
12 |
13 | .pos .order {
14 | background: #01180a;
15 | color: white;
16 | }
17 |
18 | .pos .order .orderline .info-list, .pos .order .orderline .info-list em {
19 | color: #cccccc;
20 | }
21 |
22 | .pos .leftpane {
23 | order: 2;
24 | }
25 |
26 | .pos .rightpane {
27 | order: 1;
28 | }
--------------------------------------------------------------------------------
/custom-addons/owl/static/src/pos/pos_global_state.js:
--------------------------------------------------------------------------------
1 | /** @odoo-module */
2 |
3 | import Registries from "point_of_sale.Registries"
4 | import { PosGlobalState } from "point_of_sale.models"
5 |
6 | const PosGlobalStateInherit = (models) => class extends models {
7 | constructor(obj) {
8 | super(obj);
9 | console.log("Inherited PosGlobalState")
10 | this.favorite_products = this.getFavoriteProducts()
11 | this.popupMessage = ""
12 | }
13 |
14 | async getFavoriteProducts(){
15 | const data = await this.env.services.rpc({
16 | 'model': 'product.product',
17 | 'method': 'getFavoriteProducts',
18 | 'args': [{}]
19 | })
20 |
21 | return data
22 | }
23 |
24 | async setFavoriteProducts(){
25 | this.favorite_products = await this.getFavoriteProducts()
26 | }
27 | }
28 |
29 | Registries.Model.extend(PosGlobalState, PosGlobalStateInherit)
--------------------------------------------------------------------------------
/custom-addons/owl/views/odoo_services.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Odoo Services
6 | owl.OdooServices
7 |
8 |
9 |
10 |
11 |
12 | OWL Dashboard Services
13 | owl.Dashboard
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/custom-addons/owl/views/res_partner.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | res.partner.list.view.inherit
6 | res.partner
7 |
8 |
9 |
10 | res_partner_list_view
11 |
12 |
13 |
14 |
15 |
16 | res.partner.kanban.view.inherit
17 | res.partner
18 |
19 |
20 |
21 | res_partner_kanban_view
22 |
23 |
24 |
25 |
26 |
27 | res.partner.form.view.inherit
28 | res.partner
29 |
30 |
31 |
32 | res_partner_form_view
33 |
34 |
35 | valid_email
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/custom-addons/owl/views/todo_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | owl.todo.tree.form.view
6 | owl.todo.list
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | owl.todo.list.form.view
18 | owl.todo.list
19 |
20 |
29 |
30 |
31 |
32 |
33 | Todo List
34 | owl.todo.list
35 | tree,form
36 |
37 |
38 |
39 | Todo List OWL
40 | owl.action_todo_list_js
41 |
42 |
43 |
44 |
48 |
--------------------------------------------------------------------------------
/odoo.conf:
--------------------------------------------------------------------------------
1 | [options]
2 | admin_passwd = 12345
3 | db_host = False
4 | db_port = False
5 | db_user = odoo16
6 | db_password = odoo16
7 | dbfilter = ^owl16.*$
8 | db_list = True
9 | addons_path = /Users/alferjay/Dev/odoo/v16/community/addons,/Users/alferjay/Dev/odoo/v16/owl_tutorial/custom-addons
10 | http_port = 8069
--------------------------------------------------------------------------------