Skip to content

[IMP] website_dynamic_snippet: migrate sale order cards to Interactions class #4788

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: master-optimize-xml-files-loading-aans
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file.
26 changes: 26 additions & 0 deletions addons/website_dynamic_snippet/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"name": "Website Dynamic Snippet",
"version": "1.0",
"category": "Website/Website",
"depends": ["website_sale"],
"author": "Parth Vyas",
"website": "https://www.odoo.com",
"description": """
This module provides a dynamic snippet for displaying sale order details on the website.
""",
"data": [
"views/snippets.xml",
"views/snippets/s_sale_order_cards.xml",
],
"assets": {
"web.assets_frontend": [
"website_dynamic_snippet/static/src/snippets/**/*",
],
"web.assets_tests": [
"website_dynamic_snippet/static/tests/tours/**/*",
],
},
"installable": True,
"auto_install": True,
"license": "LGPL-3",
}
90 changes: 90 additions & 0 deletions addons/website_dynamic_snippet/static/src/img/s_thumbnail.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
<t t-name="website_dynamic_snippet.s_sale_order_cards.card" t-foreach="orders" t-as="order" t-key="order.name">
<div class="col-lg-4 col-md-6 mb-4">
<div class="card h-100 shadow-sm">
<div class="card-body d-flex flex-column">
<h6 class="card-title mb-2"><t t-esc="order.name"/></h6>
<h4 class="card-text mb-2"><t t-esc="order.partner_id[1]"/></h4>
<span class="badge bg-info rounded-pill"><t t-esc="order.state"/></span>
</div>
</div>
</div>
</t>

<t t-name="website_dynamic_snippet.s_sale_order_cards.list" t-foreach="orders" t-as="order" t-key="order.name">
<li class="list-group-item d-flex flex-column align-items-center">
<div class="p-2">
<strong class="px-2">Order:</strong><t t-esc="order.name"/>
<strong class="px-2">Customer:</strong><t t-esc="order.partner_id[1]"/>
<span class="badge bg-info rounded-pill mx-2">Status: <t t-esc="order.state"/></span>
</div>
</li>
</t>
</templates>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { registry } from "@web/core/registry";
import { SaleOrderCards } from "./sale_order_cards"

const SaleOrderCardsEdit = I => class extends I {
start() {
super.start();
this.loadMoreButton.setAttribute("disabled", "true");
}
};

registry
.category("public.interactions.edit")
.add("website_dynamic_snippet.s_sale_order_cards", { Interaction: SaleOrderCards, mixin: SaleOrderCardsEdit });
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { Interaction } from "@web/public/interaction";
import { registry } from "@web/core/registry";

export class SaleOrderCards extends Interaction {
static selector = ".s_sale_order_cards";
dynamicContent = {
"#load_more_orders": {
"t-on-click": this.loadMore,
},
};

setup() {
this.noOfOrders = 10;
this.offset = 0;
this.orders = [];
}

async willStart() {
await this.fetchOrders();
}

start() {
this.loadMoreButton = this.el.querySelector("#load_more_orders")
this.loadMoreButton.removeAttribute("disabled");
this.renderOrders();
}

renderOrders() {
const target = this.el.querySelector("#sale_order_cards_container");
target.innerHTML = "";
const displayType = this.el.dataset.displayType ?? "card";
const templateName = `website_dynamic_snippet.s_sale_order_cards.${displayType}`;
if (this.orders.length) {
this.renderAt(templateName, { orders: this.orders }, target);
}
}

async fetchOrders() {
this.showConfirmOrders = this.el.dataset.showConfirmOrders === "true";
this.noOfOrders = parseInt(this.el.dataset.noOfOrders);
const domain = this.showConfirmOrders ? [["state", "=", "sale"]] : [];
const temp_orders = await this.services.orm.searchRead(
"sale.order",
domain,
["name", "partner_id", "state"],
{ limit: this.noOfOrders, offset: this.offset }
);
const loadMoreButton = this.el.querySelector("#load_more_orders");
loadMoreButton.classList.toggle("d-none", temp_orders.length === 0);
this.orders.push(...temp_orders);
}

async loadMore() {
this.offset += this.noOfOrders;
await this.fetchOrders();
this.renderOrders();
}
}

registry
.category("public.interactions")
.add("website_dynamic_snippet.s_sale_order_cards", SaleOrderCards);
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { registry } from "@web/core/registry";
import { SaleOrderCards } from "./sale_order_cards"

const SaleOrderCardsPreview = I => class extends I {
dynamicContent = {
_root: {
"t-on-mouseenter": () => {
this.el.style.backgroundColor = "#f0f0f0"
},
"t-on-mouseleave": () => {
this.el.style.backgroundColor = "";
},
},
};
};

registry
.category("public.interactions.preview")
.add("website_dynamic_snippet.s_sale_order_cards", { Interaction: SaleOrderCards, mixin: SaleOrderCardsPreview });
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import {
changeOption,
clickOnSnippet,
insertSnippet,
registerWebsitePreviewTour,
clickOnSave,
} from '@website/js/tours/tour_utils';

registerWebsitePreviewTour("snippet_sale_order_cards", {
url: "/",
edition: true,
}, () => [
...insertSnippet({ id: "s_sale_order_cards", name: "Sale Order Cards", groupName: "Website Sale" }),
...clickOnSnippet({ id: "s_sale_order_cards", name: "Sale Order Cards", groupName: "Website Sale" }),
changeOption("sale_order_cards_options", 'we-checkbox'),
{
content: "Check confirmed orders option applied",
trigger: ':iframe section[data-show-confirm-orders="true"]',
},
changeOption("sale_order_cards_options", 'we-select[data-attribute-name="displayType"] we-toggler'),
changeOption("sale_order_cards_options", 'we-button[data-select-data-attribute="list"]'),
{
content: "Check display type list applied",
trigger: ':iframe section[data-display-type="list"]',
},
changeOption("sale_order_cards_options", 'we-select[data-attribute-name="displayType"] we-toggler'),
changeOption("sale_order_cards_options", 'we-button[data-select-data-attribute="card"]'),
{
content: "Check display type card applied",
trigger: ':iframe section[data-display-type="card"]',
},
{
content: "Change number of orders option",
trigger: 'we-input[data-attribute-name="noOfOrders"] input',
run: `edit 15 && click body`,
},
{
content: "Check number of orders option applied",
trigger: ':iframe section[data-no-of-orders="15"]',
},
...clickOnSave(),
{
content: "Check for load more button",
trigger: ':iframe button[id="load_more_orders"]',
run: `click`,
},
{
content: "Check for expected number of orders loaded",
trigger: ':iframe #sale_order_cards_container > :nth-child(25)',
},
]);
1 change: 1 addition & 0 deletions addons/website_dynamic_snippet/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import test_sale_order_cards
11 changes: 11 additions & 0 deletions addons/website_dynamic_snippet/tests/test_sale_order_cards.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from odoo.tests import HttpCase, tagged


@tagged("post_install", "-at_install")
class TestSaleOrderCards(HttpCase):
def test_sale_order_cards_snippet(self):
self.start_tour(
self.env["website"].get_client_action_url("/"),
"snippet_sale_order_cards",
login="admin",
)
19 changes: 19 additions & 0 deletions addons/website_dynamic_snippet/views/snippets.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>

<template id="snippet_sale_order_cards" inherit_id="website.snippets">
<xpath expr="//snippets[@id='snippet_groups']" position="inside">
<t snippet-group="sale" t-snippet="website.s_snippet_group" string="Website Sale"
t-thumbnail="/website_dynamic_snippet/static/src/img/s_website_sale.png" />
</xpath>
<xpath expr="//snippets[@id='snippet_structure']" position="inside">
<t t-snippet="website_dynamic_snippet.s_sale_order_cards"
string="Sale Order Cards"
t-thumbnail="/website_dynamic_snippet/static/src/img/s_thumbnail.svg"
group="sale">
<keywords>sale, order, cards</keywords>
</t>
</xpath>
</template>

</odoo>
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<template id="s_sale_order_cards" name="Sale Order Cards">
<section class="s_sale_order_cards" data-no-of-orders="10"
data-preview-interaction-enabled="true">
<div class="row d-flex align-items-center" id="sale_order_cards_container">
<!-- Cards will be rendered here -->
</div>
<div class="d-flex justify-content-center my-4">
<button class="btn btn-primary d-none" id="load_more_orders">Load More Orders...</button>
</div>
</section>
</template>

<template id="s_sale_order_cards_options" inherit_id="website.snippet_options">
<xpath expr="." position="inside">
<div data-selector=".s_sale_order_cards" data-js="sale_order_cards_options">
<we-checkbox
string="Show Confirmed Orders"
data-no-preview="true"
data-select-data-attribute="false|true"
data-attribute-name="showConfirmOrders"
/>
<we-select string="Display Type" data-attribute-default-value="card"
data-attribute-name="displayType">
<we-button
data-select-data-attribute="list">List</we-button>
<we-button
data-select-data-attribute="card">Card</we-button>
</we-select>
<we-input string="Number of Orders" data-step="5" data-min="0" data-max="50"
data-select-data-attribute="" data-attribute-name="noOfOrders" />
</div>
</xpath>
</template>
</odoo>