Skip to content

18.0 dynamic content snippet gppa #751

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

Draft
wants to merge 5 commits into
base: 18.0
Choose a base branch
from
Draft
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
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"python.languageServer": "None"
}
12 changes: 1 addition & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1 @@
# Odoo tutorials

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 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`.
This is read.me file!
Empty file.
20 changes: 20 additions & 0 deletions website_dynamic_snippet/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
'name': 'Website Dynamic Snippet',
'version': '18.0.1.0.0',
'category': 'Website',
'depends': ['website_sale'],
'data': [
'views/snippets/snippets.xml',
],
'assets': {
'web.assets_frontend': [
'website_dynamic_snippet/static/src/snippets/s_dynamic_sale_order_snippet/000.xml',
'website_dynamic_snippet/static/src/snippets/s_dynamic_sale_order_snippet/000.js',
],
'website.assets_wysiwyg': [
'website_dynamic_snippet/static/src/snippets/s_dynamic_sale_order_snippet/options.js',
]
},
'installable': True,
'application': True,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/** @odoo-module **/
import { renderToElement } from "@web/core/utils/render";
import publicWidget from "@web/legacy/js/public/public_widget";

publicWidget.registry.get_product_tab = publicWidget.Widget.extend({
selector: '.categories_section',
disabledInEditableMode: false,
events: {
'click .load-more-button': '_onLoadMoreClick',
},

init() {
this._super(...arguments);
this.orm = this.bindService("orm");
this.offset = 0;
this.limit = 10;
},

async willStart() {
await this.loadCategories();
},

async loadCategories() {
if(this.$target[0].dataset.setLayout === 'list'){
this.layout = 'list';
} else {
this.layout = 'grid';
this.limit = 9;
}

const template = this.layout === 'list'
? 'website_dynamic_snippet.sale_order_snippet_list'
: 'website_dynamic_snippet.sale_order_snippet_grid';

const domain = this.$target[0].dataset.confirmOrderOnly === 'true' ? [['state', '=', 'sale']] : [];
const result = await this.orm.searchRead(
'sale.order',
domain,
['id', 'name', 'partner_id', 'amount_total', 'state'],
{
offset: this.offset,
limit: this.limit,
order: 'id ASC',
}
);
if (result && result.length) {
const content = await renderToElement(
template,
{ result: result },
);
if(this.layout === 'list') {
const newTableRows = content.querySelectorAll('.list_sale_order > tbody > tr');
const existingTableBody = this.el.querySelector('.list_sale_order > tbody');
if (this.offset === 0) {
this.el.innerHTML = '';
this.el.appendChild(content);
} else {
if (existingTableBody && newTableRows.length) {
newTableRows.forEach(row => existingTableBody.appendChild(row));
}
}
} else {
const newCardCols = content.querySelectorAll('.card_sale_order > .col-md-4');
const existingCardWrapper = this.el.querySelector('.card_sale_order');
if (this.offset === 0) {
this.el.innerHTML = '';
this.el.appendChild(content);
} else {
if (existingCardWrapper && newCardCols.length) {
newCardCols.forEach(card => existingCardWrapper.appendChild(card));
}
}
}

this.offset += result.length;
} else {
const loadMoreButton = this.el.querySelector('.load-more-button');
if (loadMoreButton) {
loadMoreButton.style.display = 'none';
}
}
},


async _onLoadMoreClick(ev) {
ev.preventDefault();
await this.loadCategories();
},
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
<t t-name="website_dynamic_snippet.sale_order_snippet_list">
<div class="container my-5 categories_section">
<h3 class="section_heading">Sale Order Details</h3>
<div class="card_list_wrapper">
<table class="table list_sale_order">
<thead>
<tr>
<th scope="col">Number</th>
<th scope="col">Customer Name</th>
<th scope="col">Status</th>
</tr>
</thead>
<tbody>
<t t-foreach="result" t-as="sale_order" t-key="sale_order.id">
<tr>
<th scope="row"><t t-esc="sale_order.id"/></th>
<td><t t-esc="sale_order.partner_id[1]"/></td>
<td><t t-esc="sale_order.state"/></td>
</tr>
</t>
</tbody>
</table>
<div class="text-center mt-3">
<button type="button" class="btn btn-primary load-more-button">
Load More
</button>
</div>
</div>
</div>
</t>

<t t-name="website_dynamic_snippet.sale_order_snippet_grid">
<div class="container my-5 categories_section">
<h3 class="section_heading">Sale Order Details</h3>
<div class="card_list_wrapper">
<div class="row card_sale_order">
<t t-foreach="result" t-as="sale_order" t-key="sale_order.id">
<div class="col-md-4 mb-4">
<div class="card h-100">
<div class="card-body">
<h5 class="card-title">Order #<t t-esc="sale_order.id"/></h5>
<p class="card-text"><strong>Customer:</strong> <t t-esc="sale_order.partner_id[1]"/></p>
<p class="card-text"><strong>Status:</strong> <t t-esc="sale_order.state"/></p>
</div>
</div>
</div>
</t>
</div>
<div class="text-center mt-3">
<button type="button" class="btn btn-primary load-more-button">
Load More
</button>
</div>
</div>
</div>
</t>
</templates>
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import options from "@web_editor/js/editor/snippets.options";

options.registry.DynamicSnippetOptions = options.Class.extend({
confirmOrderOnly(previewMode, widgetValue) {
this.$target[0].dataset.confirmOrderOnly = widgetValue;
},

setLayout(previewMode, widgetValue) {
this.$target[0].setAttribute("data-set-layout", widgetValue);
},

//--------------------------------------------------------------------------
// Private
//--------------------------------------------------------------------------

/**
* @override
*/
_computeWidgetState(methodName, params) {
if (methodName === "confirmOrderOnly") {
return this.$target[0].dataset.confirmOrderOnly;
}
if (methodName === "setLayout") {
return this.$target[0].getAttribute("data-set-layout");
}
return this._super(...arguments);
},
});
35 changes: 35 additions & 0 deletions website_dynamic_snippet/views/snippets/snippets.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>

<template id="sale_order_highlight" name="Sale Order Details">
<section class="categories_section">
<div class="container">
<div class="alert alert-info">
<h4>Your Category Highlight Tab snippet will be displayed here...
Please save to view the snippet
</h4>
</div>
</div>
</section>
</template>

<template id="category_highlight_snippet" inherit_id="website.snippets"
name="Sale Order Details Snippet">
<xpath expr="//snippets[@id='snippet_groups']" position="inside">
<t t-snippet="website_dynamic_snippet.sale_order_highlight"/>
</xpath>
</template>

<template id="s_dynamic_snippet_controller_layout" inherit_id="website.snippet_options">
<xpath expr="." position="inside">
<div data-js="DynamicSnippetOptions" data-selector=".categories_section">
<we-select data-name="snippet_data_view" string="View" data-no-preview="true" data-reload="/">
<we-button data-set-layout="grid" data-name="grid_view_opt">Grid</we-button>
<we-button data-set-layout="list" data-name="list_view_opt">List</we-button>
</we-select>
<we-checkbox data-confirm-order-only="true" class="btn btn-primary" data-no-preview="true">Show Confirm Orders</we-checkbox>
</div>
</xpath>
</template>

</odoo>