[ADD] awesome_owl, awesome_dashboard: partially implement web framework tutorial#1303
[ADD] awesome_owl, awesome_dashboard: partially implement web framework tutorial#1303daloe-odoo wants to merge 2 commits into
Conversation
157cbf9 to
79d14fc
Compare
…rk tutorial add card, counter, and todo components to awesome_owl. add almost reactive pie chart to awesome_dashboard.
387b1b1 to
af84bf0
Compare
|
@Megaaaaaa kind of ready for review |
…rerendering onPatch
Megaaaaaa
left a comment
There was a problem hiding this comment.
Hellooo 👋
Looks pretty good already, here's your review 👍 My comments are mostly about conventions that I wanted to show you or very minimal improvements to the logic.
Don't hesitate to tell me if anything is unclear or if you have question 😉
| @@ -1,8 +1,36 @@ | |||
| import { Component } from "@odoo/owl"; | |||
| import { Component, onWillStart, useState } from "@odoo/owl"; | |||
There was a problem hiding this comment.
Being extra annoying here, this import is not used 😄
| <t t-set-slot="layout-buttons"> | ||
| <button t-on-click="openCustomersKanban">Customers</button> | ||
| <button t-on-click="openLeads">Leads</button> | ||
| </t> | ||
|
|
||
| <Layout display="{controlPanel: {} }" className="'o_dashboard h-100'"> |
There was a problem hiding this comment.
Its preferable to declare the layout-buttons slot inside the <Layout> component it belongs to. As written, the buttons are defined before the component that should receive the slot. It doesn't make much a difference but we prefer it that way.
| <t t-set-slot="layout-buttons"> | |
| <button t-on-click="openCustomersKanban">Customers</button> | |
| <button t-on-click="openLeads">Leads</button> | |
| </t> | |
| <Layout display="{controlPanel: {} }" className="'o_dashboard h-100'"> | |
| <Layout display="{ controlPanel: {} }" className="'o_dashboard h-100'"> | |
| <t t-set-slot="layout-buttons"> |
| @@ -0,0 +1,54 @@ | |||
| import { Component, onMounted, onPatched, onWillStart, onWillUnmount, useRef, useState } from "@odoo/owl" | |||
There was a problem hiding this comment.
Currently import but not used 😄
| import { Component, onMounted, onPatched, onWillStart, onWillUnmount, useRef, useState } from "@odoo/owl" | |
| import { Component, onMounted, onPatched, onWillStart, onWillUnmount, useRef } from "@odoo/owl" |
| data: Object, | ||
| optional: true | ||
| } |
There was a problem hiding this comment.
This declares data as a required prop and then adds optional: true as a separate prop definition, which is not the shape Owl expects. That matters here because the dashboard statistics are loaded asynchronously, so orders_by_size can be missing on the first render. The current version can fail before the data arrives, even though the chart is naturally allowed to start empty.
| data: Object, | |
| optional: true | |
| } | |
| data: { | |
| type: Object, | |
| optional: true, | |
| }, |
| }) | ||
|
|
||
| onPatched(() => { | ||
| this.chart.destroy() |
There was a problem hiding this comment.
onPatched can run before a chart instance exists, especially sine data is optional and the first render may be empty 👍
| this.chart.destroy() | |
| this.chart?.destroy(); |
|
|
||
| export class Counter extends Component { | ||
| static template = "awesome_owl.counter"; | ||
| static prop = { |
There was a problem hiding this comment.
😉
| static prop = { | |
| static props = { |
| <label t-att-class="props.todo.isCompleted ? 'text-decoration-line-through text-muted' : '' "> | ||
| <t t-esc="props.todo.id"/>. | ||
| <t t-esc="props.todo.description"/> | ||
| <span class="fa fa-remove" t-on-click="onRemove"/> |
There was a problem hiding this comment.
Okay so I already said this to Sreedev so I guess this is the way they show it in the tutorial but being an clickable action, this should be a button not a span. It works great with the mouse but keyboard users and assistive technologies, don't forget to make this kind of action a button in the future 😄
| <span class="fa fa-remove" t-on-click="onRemove"/> | |
| <button type="button" class="btn btn-link p-0" t-on-click="onRemove"> | |
| <i class="fa fa-remove"/> | |
| </button> |
| } | ||
|
|
||
| addTodo(event) { | ||
| if (event.key === 'Enter' && event.target.value !== '') { |
There was a problem hiding this comment.
This only rejects an actually empty string, so a todo containing only spaces can still be added. It's up to you really but I would consider this a small bug in the feature. Your call 😄
| if (event.key === 'Enter' && event.target.value !== '') { | |
| if (event.key === "Enter" && event.target.value.trim() !== "") { |
| if (event.key === 'Enter' && event.target.value !== '') { | ||
| this.todos.push({ | ||
| id: this.nextId++, | ||
| description: event.target.value, |
There was a problem hiding this comment.
Then if you validate the trimmed value, you should save the trimmed value. Still your call 😄
| description: event.target.value, | |
| description: event.target.value.trim(), |
| import { onMounted, useRef } from "@odoo/owl" | ||
|
|
||
|
|
||
| export function Autofocus(refName) { |
There was a problem hiding this comment.
So this calling Owl hooks, it would be prefereable to name it like a hook so we get the intention clearer. This would be more of a useAutofocus in this case. I feel like it help makes the difference with a simple utility 👍
| export function Autofocus(refName) { | |
| export function useAutofocus(refName) { |

add card, counter, and todo components to awesome_owl. add almost reactive pie chart to awesome_dashboard.
task-6253605