Skip to content

Conversation

@ldau-odoo
Copy link

This PR adapts the e-commerce dashboard design by:

  • emphasizing the cards when there is data to display.
  • making the card active on click.
  • hiding the "To confirm" card when there is no data to display because
    it's not a common case.

task-5177259

@robodoo
Copy link

robodoo commented Oct 28, 2025

This PR targets the un-managed branch odoo-dev/odoo:master-awesome-ecommerce-dashboard-nipl, it needs to be retargeted before it can be merged.

@ldau-odoo ldau-odoo force-pushed the master-awesome-ecommerce-dashboard-ldau branch 2 times, most recently from c14465f to fdeda0a Compare October 29, 2025 13:08
Copy link

@nipl-odoo nipl-odoo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello Laetitia 👋🏻, thanks for the new design iteration, the dashboard’s looking really nice!
I’ve left a few comments on the JS diff. Not sure if you or I should handle those, so let me know if it’s on my side.

Comment on lines 18 to 23
useBus(this.env.searchModel, 'update', () => {
if(!this.getIsActiveSearchEquivalentToFilterCard(this.state.selectedFilter)) {
this.state.selectedFilter = null;
}
});

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of this, why don't you maintain a variable like I did with selectedDateFilter?
Because with this diff, if I select a similar filter as a card from the search bar, the card will stay selected, but the state variable will not be the same, which kinda feels weird for a state variable.

I would suggest setting a variable with the active filter values in this searchModel update and in onwillstart, you just compare that state variable with the current search items by sorting the same way you did in getIsActiveSearchEquivalentToFilterCard.

this.state.selectedFilter = filters;
}

getIsActiveSearchEquivalentToFilterCard(filters) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe rename to compareFilter or isSameFilter if you want a shorter name. Up to you, though :p

Comment on lines 52 to 53
html .o_web_client > .o_action_manager > .o_website_sale_dashboard_kanban_view .o_content,
html .o_web_client > .o_action_manager > .o_website_sale_dashboard_list_view .o_content {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am no CSS expert (correct me if I am wrong), but maybe

.o_website_sale_dashboard_kanban_view .o_content,
.o_website_sale_dashboard_list_view .o_content {}

this is enough, no? 🤔 Also move this to addons/website_sale/static/src/views/website_sale_kanban_view.scss and addons/website_sale/static/src/views/website_sale_list_view.scss it looks like their home.

<DateFilterButton update.bind="updateDashboardState" selectedFilter="state.selectedFilter"/>
<div class="d-none d-lg-flex border rounded-3 py-3">
<div class="o_date_filter_wrapper d-flex align-items-center">
<DateFilterButton update.bind="updateDashboardState" selectedFilter="state.selectedDateFilter"/>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe also rename DateFilterButton's prop to selectedDateFilter, it's clearer, no?

@@ -10,10 +10,17 @@ export class WebsiteSaleDashboard extends Component {
setup() {
this.state = useState({
eCommerceData: {},
selectedFilter: DATE_OPTIONS[0],
selectedDateFilter: DATE_OPTIONS[0],
selectedFilter: null,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
selectedFilter: null,
selectedFilter: [],

should be declared as an empty array since you will be maintaining an array with this variable

Comment on lines +59 to +63
if (!filters) {
return false;
}
const activeSearchFilterNames = this.env.searchModel.getSearchItems(el => el.isActive && el.type === 'filter')?.map(el => el.name).sort();
return filters.length === activeSearchFilterNames?.length && filters.sort().every((val, i) => val === activeSearchFilterNames[i]);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of comparing with the searchModel's filters, maybe you can properly maintain the state variable and compare it.

So basically state variable will contain a subset of searchModel items (only with type filters), and you use that state variable to compare with the filters array in here.

@ldau-odoo ldau-odoo force-pushed the master-awesome-ecommerce-dashboard-ldau branch from fdeda0a to 190c448 Compare October 31, 2025 14:38
@ldau-odoo
Copy link
Author

Hey @nipl-odoo,
thanks for the feedback!
I've solved most of it, I'd rather leave the js to you, you'll be more efficient than me on this one :D
A member of my team will also do a quick check

Copy link

@Brieuc-brd Brieuc-brd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good job @ldau-odoo, it looks nice 👍

I've made a first pass, see my comments below.

Thanks !

}
const filters = filterName == 'to_confirm' ? [filterName, 'from_website'] : [filterName, 'from_website','order_confirmed'];
if(this.isSameFilter(filters)) {
dashboardCardClasses.push('o_dashboard_card--active');

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you apply my suggestion you should change this class as well.

Suggested change
dashboardCardClasses.push('o_dashboard_card--active');
dashboardCardClasses.push('active');

<templates>
<t t-name="website_sale.WebsiteSaleDashboard">
<div class="o_website_sale_dashboard container-fluid d-flex flex-wrap justify-content-between align-items-start gap-3 p-3 border-bottom">
<div class="o_website_sale_dashboard container-fluid d-flex justify-content-between align-items-center gap-3 p-3 border-bottom">

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To handle easily the size of dashboard cards (and avoid custom css like this : , I wonder if it wouldn't be easier to use grid 🤔 something like this :

<div class="o_website_sale_dashboard container-fluid grid gap-3 p-3 border-bottom">
     <!-- Left Section -->
     <div class="g-col-12 g-col-lg-5">
      ...
     </div>
     <!-- Right Section -->
     <div class="g-col-7 d-none d-lg-flex">
      ...
     </div>
</div>

You could easily manage the size depending on breakpoints 👍

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I preferred to do it differently and fix the size, otherwise the right side wasn't great.

<h2 class="m-0 fw-bold o_dashboard_card_data" t-esc="state.eCommerceData['overall']['to_fulfill']"/>
<h4 class="fw-semibold text-muted o_dashboard_card_text">To Fulfill</h4>
</a>
<span class="o_dashboard_card_data fs-4 fw-bolder" t-esc="state.eCommerceData['overall']['to_fulfill']"/>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

o_dashboard_card_data is no longer used if I'm not mistaken, you can remove it (same for the other iterations).

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I kept it in order to use it to target the number and colour it (that way I can remove the famous text-body that was overwriting the colour I had defined).

</h3>
<div class="fw-semibold text-muted o_dashboard_card_text">Visitors</div>
</span>
<span class="o_dashboard_card_text fs-6 text-body fw-bold">Visitors</span>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure text-body is necessary here (same for the other iterations) ? 🤔

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(see comment above)

@ldau-odoo ldau-odoo force-pushed the master-awesome-ecommerce-dashboard-ldau branch from 190c448 to fb510a9 Compare November 4, 2025 10:42
@ldau-odoo ldau-odoo requested a review from Brieuc-brd November 4, 2025 12:06
@nipl-odoo nipl-odoo force-pushed the master-awesome-ecommerce-dashboard-nipl branch from 30351d5 to 8a3d7df Compare November 4, 2025 13:27
@ldau-odoo ldau-odoo force-pushed the master-awesome-ecommerce-dashboard-ldau branch from fb510a9 to bb0079c Compare November 4, 2025 15:52
@nipl-odoo nipl-odoo force-pushed the master-awesome-ecommerce-dashboard-nipl branch 2 times, most recently from 4aa1139 to 91a027e Compare November 6, 2025 07:23
@ldau-odoo ldau-odoo force-pushed the master-awesome-ecommerce-dashboard-ldau branch 2 times, most recently from 02ce7bb to b42e24c Compare November 12, 2025 14:40
@ldau-odoo ldau-odoo force-pushed the master-awesome-ecommerce-dashboard-ldau branch from b42e24c to 4242398 Compare November 20, 2025 11:41
@nipl-odoo nipl-odoo force-pushed the master-awesome-ecommerce-dashboard-nipl branch from 91a027e to 6464a09 Compare November 24, 2025 09:51
@ldau-odoo ldau-odoo force-pushed the master-awesome-ecommerce-dashboard-ldau branch from 4242398 to 369fb04 Compare November 24, 2025 09:54
@mano-odoo mano-odoo self-requested a review November 25, 2025 13:09
Copy link

@mano-odoo mano-odoo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good! 🤩 Just a few comment, mostly nitpicks, nice work 😄

purple: (
bg: var(--DashboardCard__purple-bg-color, #{$purple-100}),
bg-active: var(--DashboardCard__purple-bg-color--active, #{$purple-200}),
color: var(--DashboardCard__purple-color, #{$purple-600}),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would recommend going purple-700, in darkmode the color lacks just a bit of contrast 😇
image

title="Orders to Fulfill"
class="o_dashboard_card o_purple_card text-center rounded-3 p-2 shadow-sm flex-shrink-1"
t-on-click="setSearchContext"
class="o_dashboard_card btn flex-grow-1 d-md-flex d-lg-block flex-md-row align-items-md-baseline justify-content-md-center gap-md-1 g-col-4 g-col-md-4 g-col-lg-3 g-col-xxl-2 g-start-lg-1 py-2 px-4 lh-sm"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's a leftover from when you tried switching them to grid? Check other occurences

Suggested change
class="o_dashboard_card btn flex-grow-1 d-md-flex d-lg-block flex-md-row align-items-md-baseline justify-content-md-center gap-md-1 g-col-4 g-col-md-4 g-col-lg-3 g-col-xxl-2 g-start-lg-1 py-2 px-4 lh-sm"
class="o_dashboard_card btn flex-grow-1 d-md-flex d-lg-block flex-md-row align-items-md-baseline justify-content-md-center gap-md-1 py-2 px-4 lh-sm"

<div class="o_right_section align-content-center d-flex flex-wrap gap-4 flex-grow-1 justify-content-end">
<div class="o_date_filter_wrapper d-flex align-items-center w-100 w-md-auto mb-3 mb-md-0">
<DateFilterButton update.bind="updateDashboardState" selectedFilter="state.selectedFilter"/>
<div class="d-flex flex-column flex-md-row border rounded-3 pb-2 py-md-2 w-100 w-md-auto gap-2 gap-md-0 overflow-hidden">

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The overflow-hidden here It could make us loose valuable information, do we need it?

<div class="o_date_filter_wrapper d-flex align-items-center w-100 w-md-auto mb-3 mb-md-0">
<DateFilterButton update.bind="updateDashboardState" selectedFilter="state.selectedFilter"/>
<div class="d-flex flex-column flex-md-row border rounded-3 pb-2 py-md-2 w-100 w-md-auto gap-2 gap-md-0 overflow-hidden">
<div class="o_date_filter_wrapper d-flex align-items-center p-2 px-3 bg-200 bg-opacity-75">

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Super nitpicky, but p-2 is the same as py-2 here since we define the x axis to override it, I think it's cleaner to define both axis rather than overriding one 🥺

@ldau-odoo ldau-odoo force-pushed the master-awesome-ecommerce-dashboard-ldau branch from 369fb04 to df7fbf8 Compare November 25, 2025 14:46
This commit adapts the ecommerce dashboard design by:
- emphasizing the cards when there is data to display.
- making the card active on click.
- hiding the "To confirm" card when there is no data to display because
it's not a common case.

task-5177259
@ldau-odoo ldau-odoo force-pushed the master-awesome-ecommerce-dashboard-ldau branch from df7fbf8 to 9e6391e Compare November 25, 2025 15:47
@ldau-odoo ldau-odoo requested a review from mano-odoo November 25, 2025 15:49
@ldau-odoo ldau-odoo merged commit 7d434a3 into master-awesome-ecommerce-dashboard-nipl Nov 25, 2025
@ldau-odoo ldau-odoo deleted the master-awesome-ecommerce-dashboard-ldau branch November 25, 2025 15:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants