Skip to content
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
59 changes: 40 additions & 19 deletions awesome_website/__manifest__.py
Original file line number Diff line number Diff line change
@@ -1,31 +1,52 @@
{
'name': "Awesome Website",

'summary': """
"name": "Awesome Website",
"summary": """
Companion addon for the Odoo JS Framework Training
""",

'description': """
"description": """
Companion addon for the Odoo JS Framework Training
""",

'author': "Odoo",
'website': "https://www.odoo.com",

"author": "Odoo",
"website": "https://www.odoo.com",
# Categories can be used to filter modules in modules listing
# Check https://github.com/odoo/odoo/blob/19.0/odoo/addons/base/data/ir_module_category_data.xml
# for the full list
'category': 'Tutorials',
'version': '0.2',

"category": "Tutorials",
"version": "0.2",
# any module necessary for this one to work correctly
'depends': ['website'],
'application': True,
'installable': True,
'data': [
'data/images.xml',
"depends": ["website"],
"application": True,
"installable": True,
"data": [
"data/images.xml",
"views/snippets/snippets.xml",
"views/snippets/s_image_comparison.xml",
"views/snippets/static_banner.xml",
],
'assets': {
"assets": {
"web.assets_frontend": [
"awesome_website/static/src/interactions/**/*",
"awesome_website/static/src/snippets/**/*",
"awesome_website/static/src/components/**/*",
("remove", "awesome_website/static/src/interactions/**/*.edit.*"),
("remove", "awesome_website/static/src/snippets/**/*.edit.*"),
],
"website.assets_inside_builder_iframe": [
"awesome_website/static/src/snippets/**/*.edit.*",
],
"website.website_builder_assets": [
"awesome_website/static/src/builder/**/*",
],
"web.assets_unit_tests": [
"website/static/tests/builder/website_helpers.js",
"awesome_website/static/tests/interactions/**/*",
"awesome_website/static/tests/builder/**/*",
],
"web.assets_unit_tests_setup": [
"awesome_website/static/src/interactions/**/*",
"awesome_website/static/src/snippets/**/*",
"awesome_website/static/src/builder/**/*",
],
},
'license': 'AGPL-3'
"license": "AGPL-3",
}
18 changes: 18 additions & 0 deletions awesome_website/static/src/builder/image_comparison_colorslide.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
<t t-name="awesome_website.imageComparisonColorSlide">
<BuilderRow label.translate="Pick Slider Color">
<BuilderColorPicker
styleAction="'background-color'"
applyTo="'.o_image_comparison_handle'"/>
</BuilderRow>
</t>
<t t-inherit="website.BuilderOptions" t-inherit-mode="extension">
<xpath expr="//t[@id='snippet_specific_options']" position="after">
<slider_color_picker
template="awesome_website.imageComparisonColorSlide"
selector=".s_image_comparison"/>
</xpath>
</t>
</templates>

14 changes: 14 additions & 0 deletions awesome_website/static/src/components/static_banner.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Component, xml } from "@odoo/owl";
import { registry } from "@web/core/registry";


export class StaticBanner extends Component {
static template = xml`<h3 class="align-items-center">Hello, <t t-out="this.props.name"/>!</h3>`
static props = {
name: {
type: String,
},
};
}

registry.category("public_components").add("static_banner", StaticBanner);
18 changes: 10 additions & 8 deletions awesome_website/static/src/interactions/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@ import { registry } from "@web/core/registry";
import { Interaction } from "@web/public/interaction";

class Main extends Interaction {
/* Interaction's lifecycle methods:
static selector = "main";

setup() { }
async willStart() { }
start() { }
destroy() { }

*/
dynamicContent = {
_root: {
"t-out": () => {
const now = new Date();
return now.toLocaleString('en-US');
}
}
};
}

registry.category("public.interactions").add("awesome_website.main", Main);
// registry.category("public.interactions").add("awesome_website.main", Main);
41 changes: 41 additions & 0 deletions awesome_website/static/src/interactions/mouse_follower.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { registry } from "@web/core/registry";
import { Interaction } from "@web/public/interaction";

export class MouseFollower extends Interaction {
static selector = "#wrapwrap";

dynamicSelectors = {
...this.dynamicSelectors,
_highlighter: () => this.highlighter,
}

dynamicContent = {
_root: {
"t-on-pointermove": this.debounced(this.onPointerMove, 5),
},
_highlighter: {
"t-att-style": () => ({
top: `${this.my}px`,
left: `${this.mx}px`,
}),
},
};

setup() {
this.mx = 0;
this.my = 0;
this.highlighter = document.createElement("div");
this.highlighter.classList.add("x_mouse_follower");
}

start() {
this.insert(this.highlighter);
}

onPointerMove(ev) {
this.mx = ev.clientX;
this.my = ev.clientY;
}
}

registry.category("public.interactions").add("awesome_website.mouse_follower", MouseFollower);
Original file line number Diff line number Diff line change
@@ -1,5 +1,23 @@
.o_image_comparison_container {
.o_image_comparison_horizontal & {
--slider-left: var(--slider-img-left);
--slider-right: calc(var(--slider-left) + 1%);
--slider-top: 0;
--slider-bottom: 100%;

.o_rtl & {
--slider-right: var(--slider-img-right);
--slider-left: calc(var(--slider-right) - 1%);
}
}
.o_image_comparison_vertical & {
--slider-top: var(--slider-img-top);
--slider-bottom: calc(var(--slider-top) + 1%);
--slider-left: var(--slider-img-left);
--slider-right: var(--slider-img-right);
}
.o_image_comparison_slider {
pointer-events: none;
clip-path: rect(0 calc(var(--slider-position) + 1%) 100% var(--slider-position));

.o_rtl & {
Expand Down
35 changes: 35 additions & 0 deletions awesome_website/static/src/snippets/s_image_comparison/000.scss
Original file line number Diff line number Diff line change
@@ -1,6 +1,41 @@
.o_image_comparison_container {
--slider-position: 50%;

.o_image_comparison_horizontal & {
--handle-left: var(--slider-position);
--handle-top: 50%;
--slider-img-left: var(--slider-position);
--slider-img-right: 100%;
--slider-img-top: 0;
--slider-cursor: ew-resize;
--slider-height: 100vh;
--slider-width: 4px;
--slider-margin-inline: -2px;
--slider-margin-block: 0;
--slider-writing-mode: horizontal-tb;
--slider-transform: unset;

.o_rtl & {
--slider-img-left: 0;
--slider-img-right: calc(100% - var(--slider-position));
}
}
.o_image_comparison_vertical & {
--handle-left: 50%;
--handle-top: var(--slider-position);
--slider-img-top: var(--slider-position);
--slider-img-left: 0;
--slider-img-right: 100%;
--slider-cursor: ns-resize;
--slider-height: 4px;
--slider-width: 100vw;
--slider-margin-inline: 0;
--slider-margin-block: -2px;
--slider-writing-mode: vertical-rl;
--slider-transform: scaleY(-1);
}


img {
grid-area: 1 / 1;
width: 100%;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { registry } from "@web/core/registry";
import { ImageComparison } from "./image_comparison";

const ImageComparisonEdit = (I) =>
class extends I {
onSliderSlide() { }
};

registry.category("public.interactions.edit").add("awesome_website.image_comparison", {
Interaction: ImageComparison,
mixin: ImageComparisonEdit,
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { registry } from "@web/core/registry";
import { Interaction } from "@web/public/interaction";

export class ImageComparison extends Interaction {
static selector = ".s_image_comparison";

dynamicContent = {
".o_image_comparison_slider": {
"t-on-input": this.debounced(this.onSliderSlide, 5)
},
".o_image_comparison_container": {
"t-att-style": () => ({
"--slider-position": this.sliderPosition,
}),
},
};

setup() {
this.sliderPosition = "50%";
}

onSliderSlide() {
let value = document.querySelector(".o_image_comparison_slider").value;
this.sliderPosition = `${value}%`;
}
}

registry.category("public.interactions").add("awesome_website.image_comparison", ImageComparison);
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { expect, manuallyDispatchProgrammaticEvent, test } from "@odoo/hoot";
import { defineWebsiteModels, setupWebsiteBuilderWithSnippet } from "@website/../tests/builder/website_helpers";
import { contains, defineStyle } from "@web/../tests/web_test_helpers";
import { animationFrame, queryOne } from "@odoo/hoot-dom";

defineWebsiteModels();

test("Change slider handle color using the custom builder option", async () => {
defineStyle(`* { transition: none !important; }`);
await setupWebsiteBuilderWithSnippet("s_image_comparison", { loadIframeBundles: true });

await contains(":iframe .s_image_comparison").click();

expect("[data-label='Pick Slider Color']").toHaveCount(1);

await contains("[data-label='Pick Slider Color'] .o_we_color_preview").click();

await contains(".o-hb-colorpicker-popover .custom-tab").click();
await animationFrame();

const hexInput = queryOne(".o-hb-colorpicker-popover input[data-color-method='hex']");
expect(hexInput).toBeDisplayed();
hexInput.value = "#ff0000";
await manuallyDispatchProgrammaticEvent(hexInput, "input", { bubbles: true });
await animationFrame();

expect(":iframe .s_image_comparison .o_image_comparison_handle").toHaveStyle({
"background-color": "rgb(255, 0, 0)",
});
});
34 changes: 34 additions & 0 deletions awesome_website/static/tests/interactions/image_comparison.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { advanceTime, expect, manuallyDispatchProgrammaticEvent, queryOne, test } from "@odoo/hoot";
import { setupInteractionWhiteList, startInteractions } from "@web/../tests/public/helpers";
import { defineStyle } from "@web/../tests/web_test_helpers";

setupInteractionWhiteList("awesome_website.image_comparison");

test("image comparison slider should update the value of the input.", async () => {
defineStyle(`* { transition: none !important; }`);
const { core } = await startInteractions(`
<section class="s_image_comparison o_image_comparison_horizontal pb64 pt64">
<div class="o_container_small">
<div class="o_image_comparison_container position-relative d-grid overflow-hidden">
<img src="/web/image/awesome_website.s_image_comparison_01" class="o_image_before img img-fluid object-fit-cover" alt="" loading="lazy" data-mimetype="image/webp"/>
<img src="/web/image/awesome_website.s_image_comparison_02" class="o_image_after img img-fluid object-fit-cover" alt="" loading="lazy" data-mimetype="image/webp"/>
<input type="range" min="0" max="100" class="o_image_comparison_slider position-absolute"/>
<div class="o_image_comparison_handle position-absolute translate-middle rounded-circle pe-none"/>
</div>
</div>
</section>
`);

expect(core.interactions).toHaveLength(1);
expect("input").toHaveStyle({ "--slider-position": "50%" });

for (var input_value = 10; input_value <= 100; input_value += 10) {
let input = queryOne("input");
input.value = `${input_value}`;
await manuallyDispatchProgrammaticEvent(input, "input", { bubbles: true });
await advanceTime(5);

expect("input").toHaveStyle({ "--slider-position": `${input_value}%` });
}

});
17 changes: 12 additions & 5 deletions awesome_website/views/snippets/s_image_comparison.xml
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>

<template id="s_image_comparison" name="Image Comparison">
<!-- Your snippet here -->
</template>

<template id="s_image_comparison" name="Image Comparison">
<section class="s_image_comparison o_image_comparison_horizontal pb64 pt64">
<div class="o_container_small">
<div class="o_image_comparison_container position-relative d-grid overflow-hidden">
<img src="/web/image/awesome_website.s_image_comparison_01" class="o_image_before img img-fluid object-fit-cover" alt="" loading="lazy" data-mimetype="image/webp"/>
<img src="/web/image/awesome_website.s_image_comparison_02" class="o_image_after img img-fluid object-fit-cover" alt="" loading="lazy" data-mimetype="image/webp"/>
<input type="range" min="0" max="100" class="o_image_comparison_slider position-absolute"/>
<div class="o_image_comparison_handle position-absolute translate-middle rounded-circle pe-none"/>
</div>
</div>
</section>
</template>
</odoo>
15 changes: 15 additions & 0 deletions awesome_website/views/snippets/snippets.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="snippets" inherit_id="website.snippets">
<xpath expr="//t[@t-snippet='website.s_picture']" position="before">
<t t-snippet="awesome_website.s_image_comparison" string="Image Comparison" group="images">
<keywords>image comparison, before, after, compare, side-by-side, photo, picture, contrast, split, match, slider</keywords>
</t>
</xpath>
<xpath expr="//t[@t-snippet='website.s_picture']" position="before">
<t t-snippet="awesome_website.static_banner" string="Static Banner" group="images">
<keywords>static, banner, static banner, hello</keywords>
</t>
</xpath>
</template>
</odoo>
8 changes: 8 additions & 0 deletions awesome_website/views/snippets/static_banner.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="static_banner" name="Static Banner Snippet">
<section>
<owl-component name="static_banner" props='{"name": "World"}'/>
</section>
</template>
</odoo>