Commit eeef7874 authored by Tibor Goldschwendt's avatar Tibor Goldschwendt Committed by Commit Bot

[ntp][modules] Render shopping module

Screenshot: https://screenshot.googleplex.com/8XenkGQNbhfpQKv

Fixed: 1130855
Change-Id: Ieb2ab938047b5fcc4fe1bc689661369ec5bf22c1
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2431783
Commit-Queue: Tibor Goldschwendt <tiborg@chromium.org>
Reviewed-by: default avatarEsmael Elmoslimany <aee@chromium.org>
Cr-Commit-Position: refs/heads/master@{#811009}
parent 58957734
......@@ -70,13 +70,13 @@
ntp-fakebox,
ntp-realbox {
flex-shrink: 0;
margin-bottom: 32px;
}
ntp-fakebox,
ntp-realbox,
ntp-module-wrapper {
flex-shrink: 0;
width: var(--ntp-search-box-width);
}
......
......@@ -3,6 +3,8 @@
background-color: var(--ntp-background-override-color);
border: solid var(--ntp-border-color) 1px;
border-radius: 5px;
display: block;
overflow: hidden;
}
#header {
......@@ -25,7 +27,6 @@
align-items: center;
display: flex;
justify-content: center;
overflow: hidden;
}
</style>
<div id="header">
......
<style>
:host {
box-sizing: border-box;
display: block;
height: 100%;
padding-inline-end: 15px;
padding-inline-start: 15px;
width: 100%;
}
#products {
display: flex;
flex-direction: row;
}
.product {
border-radius: 4px;
display: flex;
flex-direction: column;
outline: none;
text-decoration: none;
width: 120px;
}
:host-context(.focus-outline-visible) .product:focus {
box-shadow: var(--ntp-focus-shadow);
}
.product + .product {
margin-inline-start: 16px;
}
.image {
background: #F6F6F6;
border-radius: 4px;
box-sizing: border-box;
height: 120px;
margin-bottom: 8px;
padding: 10px;
width: 120px;
}
img {
height: 100%;
object-fit: contain;
width: 100%;
}
.price {
color: var(--cr-primary-text-color);
font-size: 13px;
font-weight: bold;
height: 14px;
line-height: 15px;
margin-bottom: 8px;
}
.name {
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
color: var(--cr-primary-text-color);
display: -webkit-box;
font-size: 12px;
height: 40px;
line-height: 20px;
margin-bottom: 5px;
overflow: hidden;
}
.info {
color: var(--cr-secondary-text-color);
font-size: 11px;
height: 13px;
text-overflow: ellipsis;
}
#relatedSearches {
display: flex;
flex-direction: row;
margin-top: 16px;
}
.pill {
align-items: center;
border: solid var(--ntp-border-color) 1px;
border-radius: 16px;
box-sizing: border-box;
display: flex;
flex-direction: row;
flex-shrink: 0;
height: 32px;
outline: none;
text-decoration: none;
}
:host-context(.focus-outline-visible) .pill:focus {
box-shadow: var(--ntp-focus-shadow);
}
.pill + .pill {
margin-inline-start: 8px;
}
.loupe {
-webkit-mask-image: url(search.svg);
-webkit-mask-repeat: no-repeat;
-webkit-mask-size: 100%;
background-color: var(--cr-secondary-text-color);
height: 16px;
margin-inline-start: 12px;
width: 16px;
}
.search-text {
color: var(--cr-primary-text-color);
font-size: 13px;
margin-inline-end: 12px;
margin-inline-start: 8px;
}
</style>
<div id="products">
<template is="dom-repeat" id="productsRepeat"
items="[[shoppingTask.products]]">
<a class="product" href="[[item.targetUrl.url]]">
<div class="image">
<img is="ntp-img" auto-src="[[item.imageUrl.url]]"></img>
</div>
<div class="price">[[item.price]]</div>
<div class="name" title="[[item.name]]">[[item.name]]</div>
<div class="info">[[item.info]]</div>
</a>
</template>
</div>
<div id="relatedSearches">
<template is="dom-repeat" id="relatedSearchesRepeat"
items="[[shoppingTask.relatedSearches]]">
<a class="pill" href="[[item.targetUrl.url]]">
<div class="loupe"></div>
<div class="search-text">[[item.text]]</div>
</a>
</template>
</div>
......@@ -2,8 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
import '../../img.js';
import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
import {ModuleDescriptor} from '../module_descriptor.js';
import {ShoppingTasksHandlerProxy} from './shopping_tasks_handler_proxy.js';
......@@ -22,25 +23,34 @@ class ShoppingTasksModuleElement extends PolymerElement {
return html`{__html_template__}`;
}
constructor() {
super();
ShoppingTasksHandlerProxy.getInstance()
.handler.getPrimaryShoppingTask()
.then(data => {
// TODO(crbug.com/1130855): Do something useful with the data.
console.log(data);
});
static get properties() {
return {
/** @type {shoppingTasks.mojom.ShoppingTask} */
shoppingTask: Object,
};
}
}
customElements.define(
ShoppingTasksModuleElement.is, ShoppingTasksModuleElement);
/** @return {!Promise<?{element: !HTMLElement, title: string}>} */
async function createModule() {
const {shoppingTask} = await ShoppingTasksHandlerProxy.getInstance()
.handler.getPrimaryShoppingTask();
if (!shoppingTask) {
return null;
}
const element = new ShoppingTasksModuleElement();
element.shoppingTask = shoppingTask;
return {
element: element,
title: shoppingTask.title,
};
}
/** @type {!ModuleDescriptor} */
export const shoppingTasksDescriptor = new ModuleDescriptor(
/*id=*/ 'shopping_tasks',
/*name=*/ 'Shopping Tasks',
/*heightPx=*/ 260, () => Promise.resolve({
element: new ShoppingTasksModuleElement(),
title: 'Shopping Tasks',
}));
/*heightPx=*/ 270, createModule);
......@@ -18,18 +18,88 @@ suite('NewTabPageModulesShoppingTasksModuleTest', () => {
testProxy = TestBrowserProxy.fromClass(ShoppingTasksHandlerProxy);
testProxy.handler = TestBrowserProxy.fromClass(
shoppingTasks.mojom.ShoppingTasksHandlerRemote);
testProxy.handler.setResultFor(
'getPrimaryShoppingTask', Promise.resolve(null));
ShoppingTasksHandlerProxy.instance_ = testProxy;
});
test('creates module', async () => {
test('creates no module if no task', async () => {
// Arrange.
testProxy.handler.setResultFor(
'getPrimaryShoppingTask', Promise.resolve({shoppingTask: null}));
// Act.
await shoppingTasksDescriptor.initialize();
// Assert.
assertEquals(1, testProxy.handler.getCallCount('getPrimaryShoppingTask'));
assertEquals(null, shoppingTasksDescriptor.element);
});
test('creates module if task', async () => {
// Arrange.
const shoppingTask = {
title: 'Hello world',
products: [
{
name: 'foo',
imageUrl: {url: 'https://foo.com/img.png'},
price: '1 gazillion dollars',
info: 'foo info',
targetUrl: {url: 'https://foo.com'},
},
{
name: 'bar',
imageUrl: {url: 'https://bar.com/img.png'},
price: '2 gazillion dollars',
info: 'bar info',
targetUrl: {url: 'https://bar.com'},
},
],
relatedSearches: [
{
text: 'baz',
targetUrl: {url: 'https://baz.com'},
},
{
text: 'blub',
targetUrl: {url: 'https://blub.com'},
},
],
};
testProxy.handler.setResultFor(
'getPrimaryShoppingTask', Promise.resolve({shoppingTask}));
// Act.
await shoppingTasksDescriptor.initialize();
const module = shoppingTasksDescriptor.element;
document.body.append(module);
module.$.productsRepeat.render();
module.$.relatedSearchesRepeat.render();
// Assert.
const products = Array.from(module.shadowRoot.querySelectorAll('.product'));
const pills = Array.from(module.shadowRoot.querySelectorAll('.pill'));
assertEquals(1, testProxy.handler.getCallCount('getPrimaryShoppingTask'));
assertEquals(2, products.length);
assertEquals(2, pills.length);
assertEquals('https://foo.com/', products[0].href);
assertEquals(
'https://foo.com/img.png', products[0].querySelector('img').autoSrc);
assertEquals(
'1 gazillion dollars', products[0].querySelector('.price').innerText);
assertEquals('foo', products[0].querySelector('.name').innerText);
assertEquals('foo', products[0].querySelector('.name').title);
assertEquals('foo info', products[0].querySelector('.info').innerText);
assertEquals('https://bar.com/', products[1].href);
assertEquals(
'https://bar.com/img.png', products[1].querySelector('img').autoSrc);
assertEquals(
'2 gazillion dollars', products[1].querySelector('.price').innerText);
assertEquals('bar', products[1].querySelector('.name').innerText);
assertEquals('bar', products[1].querySelector('.name').title);
assertEquals('bar info', products[1].querySelector('.info').innerText);
assertEquals('https://baz.com/', pills[0].href);
assertEquals('baz', pills[0].querySelector('.search-text').innerText);
assertEquals('https://blub.com/', pills[1].href);
assertEquals('blub', pills[1].querySelector('.search-text').innerText);
});
});
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment