Bug 1514006 - Part 3, add impression and click pings for CardGrid and List (#4671)
This commit is contained in:
Родитель
3fc40b433d
Коммит
62c87514b3
|
@ -16,29 +16,43 @@ import {TopSites} from "content-src/components/DiscoveryStreamComponents/TopSite
|
|||
// To enforce that, we define various maximium items for individual components as an extra check.
|
||||
// Note that these values are subject to the future changes of the specs.
|
||||
const MAX_ROWS_HERO = 5;
|
||||
// const MAX_ROWS_LISTS = 5;
|
||||
// const MAX_ROWS_CARDGRID = 8;
|
||||
const MAX_ROWS_LISTS = 5;
|
||||
const MAX_ROWS_CARDGRID = 8;
|
||||
|
||||
export class _DiscoveryStreamBase extends React.PureComponent {
|
||||
extractRows(component, limit) {
|
||||
if (component.data && component.data.recommendations) {
|
||||
const items = Math.min(limit, component.properties.items || component.data.recommendations.length);
|
||||
return component.data.recommendations.slice(0, items);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
renderComponent(component) {
|
||||
let rows;
|
||||
|
||||
switch (component.type) {
|
||||
case "TopSites":
|
||||
return (<TopSites />);
|
||||
case "SectionTitle":
|
||||
return (<SectionTitle />);
|
||||
case "CardGrid":
|
||||
return (<CardGrid
|
||||
title={component.header && component.header.title}
|
||||
data={component.data}
|
||||
feed={component.feed}
|
||||
style={component.properties.style}
|
||||
type={component.type}
|
||||
dispatch={this.props.dispatch}
|
||||
items={component.properties.items} />);
|
||||
rows = this.extractRows(component, MAX_ROWS_CARDGRID);
|
||||
return (
|
||||
<ImpressionStats rows={rows} dispatch={this.props.dispatch} source={component.type}>
|
||||
<CardGrid
|
||||
title={component.header && component.header.title}
|
||||
data={component.data}
|
||||
feed={component.feed}
|
||||
style={component.properties.style}
|
||||
type={component.type}
|
||||
dispatch={this.props.dispatch}
|
||||
items={component.properties.items} />
|
||||
</ImpressionStats>
|
||||
);
|
||||
case "Hero":
|
||||
const items = Math.min(MAX_ROWS_HERO,
|
||||
component.properties.items || (component.data ? component.data.recommendations.length : 0));
|
||||
const rows = component.data ? component.data.recommendations.slice(0, items) : [];
|
||||
rows = this.extractRows(component, MAX_ROWS_HERO);
|
||||
return (
|
||||
<ImpressionStats rows={rows} dispatch={this.props.dispatch} source={component.type}>
|
||||
<Hero
|
||||
|
@ -47,15 +61,21 @@ export class _DiscoveryStreamBase extends React.PureComponent {
|
|||
style={component.properties.style}
|
||||
type={component.type}
|
||||
dispatch={this.props.dispatch}
|
||||
items={items} />
|
||||
items={component.properties.items} />
|
||||
</ImpressionStats>
|
||||
);
|
||||
case "HorizontalRule":
|
||||
return (<HorizontalRule />);
|
||||
case "List":
|
||||
return (<List
|
||||
feed={component.feed}
|
||||
header={component.header} />);
|
||||
rows = this.extractRows(component, MAX_ROWS_LISTS);
|
||||
return (
|
||||
<ImpressionStats rows={rows} dispatch={this.props.dispatch} source={component.type}>
|
||||
<List
|
||||
feed={component.feed}
|
||||
type={component.type}
|
||||
header={component.header} />
|
||||
</ImpressionStats>
|
||||
);
|
||||
default:
|
||||
return (<div>{component.type}</div>);
|
||||
}
|
||||
|
|
|
@ -8,17 +8,19 @@ export class DSCard extends React.PureComponent {
|
|||
}
|
||||
|
||||
onLinkClick(event) {
|
||||
this.props.dispatch(ac.UserEvent({
|
||||
event: "CLICK",
|
||||
source: this.props.type.toUpperCase(),
|
||||
action_position: this.props.index,
|
||||
}));
|
||||
if (this.props.dispatch) {
|
||||
this.props.dispatch(ac.UserEvent({
|
||||
event: "CLICK",
|
||||
source: this.props.type.toUpperCase(),
|
||||
action_position: this.props.index,
|
||||
}));
|
||||
|
||||
this.props.dispatch(ac.ImpressionStats({
|
||||
source: this.props.type.toUpperCase(),
|
||||
click: 0,
|
||||
tiles: [{id: this.props.id, pos: this.props.index}],
|
||||
}));
|
||||
this.props.dispatch(ac.ImpressionStats({
|
||||
source: this.props.type.toUpperCase(),
|
||||
click: 0,
|
||||
tiles: [{id: this.props.id, pos: this.props.index}],
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
|
|
|
@ -9,17 +9,19 @@ export class Hero extends React.PureComponent {
|
|||
}
|
||||
|
||||
onLinkClick(event) {
|
||||
this.props.dispatch(ac.UserEvent({
|
||||
event: "CLICK",
|
||||
source: this.props.type.toUpperCase(),
|
||||
action_position: 0,
|
||||
}));
|
||||
if (this.props.dispatch) {
|
||||
this.props.dispatch(ac.UserEvent({
|
||||
event: "CLICK",
|
||||
source: this.props.type.toUpperCase(),
|
||||
action_position: 0,
|
||||
}));
|
||||
|
||||
this.props.dispatch(ac.ImpressionStats({
|
||||
source: this.props.type.toUpperCase(),
|
||||
click: 0,
|
||||
tiles: [{id: this.heroRec.id, pos: 0}],
|
||||
}));
|
||||
this.props.dispatch(ac.ImpressionStats({
|
||||
source: this.props.type.toUpperCase(),
|
||||
click: 0,
|
||||
tiles: [{id: this.heroRec.id, pos: 0}],
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
|
|
|
@ -1,31 +1,53 @@
|
|||
import {actionCreators as ac} from "common/Actions.jsm";
|
||||
import {connect} from "react-redux";
|
||||
import React from "react";
|
||||
|
||||
/**
|
||||
* @note exported for testing only
|
||||
*/
|
||||
export function ListItem(props) {
|
||||
export class ListItem extends React.PureComponent {
|
||||
// TODO performance: get feeds to send appropriately sized images rather
|
||||
// than waiting longer and scaling down on client?
|
||||
return (
|
||||
<li className="ds-list-item">
|
||||
<a className="ds-list-item-link" href={props.url}>
|
||||
<div className="ds-list-item-text">
|
||||
<div className="ds-list-item-title">
|
||||
<b>
|
||||
{props.title}
|
||||
</b>
|
||||
</div>
|
||||
<div className="ds-list-item-info">
|
||||
{`${props.domain} · TODO:Topic`}
|
||||
</div>
|
||||
</div>
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.onLinkClick = this.onLinkClick.bind(this);
|
||||
}
|
||||
|
||||
<img className="ds-list-image" src={props.image_src} />
|
||||
</a>
|
||||
onLinkClick(event) {
|
||||
if (this.props.dispatch) {
|
||||
this.props.dispatch(ac.UserEvent({
|
||||
event: "CLICK",
|
||||
source: this.props.type.toUpperCase(),
|
||||
action_position: this.props.index,
|
||||
}));
|
||||
|
||||
</li>
|
||||
);
|
||||
this.props.dispatch(ac.ImpressionStats({
|
||||
source: this.props.type.toUpperCase(),
|
||||
click: 0,
|
||||
tiles: [{id: this.props.id, pos: this.props.index}],
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<li className="ds-list-item">
|
||||
<a className="ds-list-item-link" href={this.props.url} onClick={this.onLinkClick}>
|
||||
<div className="ds-list-item-text">
|
||||
<div className="ds-list-item-title">
|
||||
<b>
|
||||
{this.props.title}
|
||||
</b>
|
||||
</div>
|
||||
<div className="ds-list-item-info">
|
||||
{`${this.props.domain} · TODO:Topic`}
|
||||
</div>
|
||||
</div>
|
||||
<img className="ds-list-image" src={this.props.image_src} />
|
||||
</a>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -41,7 +63,7 @@ export function _List(props) {
|
|||
const recs = feed.data.recommendations;
|
||||
|
||||
let recMarkup = recs.slice(0, props.items).map((rec, index) => (
|
||||
<ListItem {...rec} key={`ds-list-item-$index`} />)
|
||||
<ListItem {...rec} key={`ds-list-item-${index}`} index={index} type={props.type} dispatch={props.dispatch} />)
|
||||
);
|
||||
|
||||
return (
|
||||
|
|
Загрузка…
Ссылка в новой задаче