Skip to content

Commit

Permalink
Merge pull request mozilla#207 from mozilla/vendor-placeholder
Browse files Browse the repository at this point in the history
Fix mozilla#205, fix mozilla#198: Include static vendor info in add-on.
  • Loading branch information
Osmose authored Oct 24, 2018
2 parents 2410ed5 + c598dd6 commit 9813ba8
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 14 deletions.
8 changes: 1 addition & 7 deletions src/background/extraction.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,7 @@ import {validatePropType} from 'commerce/utils';
* @param {MessageSender} sender
* The sender for the content script that extracted this product
*/
export async function handleExtractedProductData(message, sender) {
// Fetch the favicon, which the content script cannot do itself.
const extractedProduct = {
...message.extractedProduct,
vendorFaviconUrl: sender.tab ? sender.tab.favIconUrl : '',
};

export async function handleExtractedProductData({extractedProduct}, sender) {
// Do nothing if the extracted product is missing fields.
const result = validatePropType(extractedProduct, extractedProductShape);
if (result !== undefined) {
Expand Down
5 changes: 4 additions & 1 deletion src/background/price_alerts.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
showPriceAlert,
} from 'commerce/state/prices';
import {getProduct} from 'commerce/state/products';
import {getVendor} from 'commerce/state/vendors';
import {recordEvent} from 'commerce/telemetry/extension';

/**
Expand Down Expand Up @@ -48,6 +49,8 @@ export function handlePriceAlerts() {
const product = getProduct(state, alert.productId);
const originalPrice = getOldestPriceForProduct(state, alert.productId);
const highPriceAmount = Dinero({amount: alert.highPriceAmount});
const vendor = getVendor(state, product.url);
const vendorName = vendor ? vendor.name : new URL(product.url).hostname;

// Display notification
const original = originalPrice.amount.toFormat('$0.00');
Expand All @@ -56,7 +59,7 @@ export function handlePriceAlerts() {
browser.notifications.create(alert.priceId, {
type: 'basic',
title: `Price Alert: ${product.title}`,
message: `Placeholder · Originally ${original}, high of ${high}, now ${now}`,
message: `${vendorName} · Originally ${original}, high of ${high}, now ${now}`,
});

// Update state now that we've shown it
Expand Down
10 changes: 7 additions & 3 deletions src/browser_action/components/ProductCard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
} from 'commerce/state/prices';
import {productShape} from 'commerce/state/products';
import * as productActions from 'commerce/state/products';
import {getVendor, vendorShape} from 'commerce/state/vendors';
import {recordEvent} from 'commerce/telemetry/extension';

import 'commerce/browser_action/components/ProductCard.css';
Expand All @@ -28,6 +29,7 @@ import 'commerce/browser_action/components/ProductCard.css';
latestPrice: getLatestPriceForProduct(state, props.product.id),
originalPrice: getOldestPriceForProduct(state, props.product.id),
activePriceAlert: getActivePriceAlertForProduct(state, props.product.id),
vendor: getVendor(state, props.product.url),
}),
{
setDeletionFlag: productActions.setDeletionFlag,
Expand All @@ -44,13 +46,15 @@ export default class ProductCard extends React.Component {
latestPrice: priceWrapperShape.isRequired,
originalPrice: priceWrapperShape.isRequired,
activePriceAlert: priceAlertShape,
vendor: vendorShape,

// Dispatch props
setDeletionFlag: pt.func.isRequired,
}

static defaultProps = {
activePriceAlert: null,
vendor: null,
}

/**
Expand Down Expand Up @@ -89,7 +93,7 @@ export default class ProductCard extends React.Component {
}

render() {
const {activePriceAlert, latestPrice, originalPrice, product} = this.props;
const {activePriceAlert, latestPrice, originalPrice, product, vendor} = this.props;

if (product.isDeleted) {
return (
Expand Down Expand Up @@ -131,8 +135,8 @@ export default class ProductCard extends React.Component {
<h3 className="title" title={product.title}>{product.title}</h3>

<div className="details">
{product.vendorFaviconUrl && (
<img className="vendor-favicon" src={product.vendorFaviconUrl} alt="" />
{vendor && vendor.faviconUrl && (
<img className="vendor-favicon" src={vendor.faviconUrl} alt="" />
)}
<span
className={`latest-price ${priceDifference < 0 ? 'price-decrease' : ''}`}
Expand Down
10 changes: 10 additions & 0 deletions src/state/migrations.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,16 @@ const MIGRATIONS = [
}),
};
},

function removeVendorFaviconUrl(state) {
return {
...state,
products: state.products.map((product) => {
const {vendorFaviconUrl, ...newProduct} = product;
return newProduct;
}),
};
},
];

// Actions
Expand Down
3 changes: 0 additions & 3 deletions src/state/products.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ export const productShape = pt.shape({
url: pt.string.isRequired,
image: pt.string.isRequired,
isDeleted: pt.bool.isRequired,
vendorFaviconUrl: pt.string.isRequired,
anonId: pt.string.isRequired,
});

Expand All @@ -38,7 +37,6 @@ export const extractedProductShape = pt.shape({
image: pt.string.isRequired,
price: pt.number.isRequired,
date: pt.string.isRequired,
vendorFaviconUrl: pt.string,
});


Expand Down Expand Up @@ -196,7 +194,6 @@ export function getProductFromExtracted(data, anonId) {
title: data.title,
url: data.url,
image: data.image,
vendorFaviconUrl: data.vendorFaviconUrl || '',
isDeleted: false,
anonId,
};
Expand Down
60 changes: 60 additions & 0 deletions src/state/vendors.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/**
* Redux duck for vendors that sell products.
* @module
*/

import pt from 'prop-types';

// Types

export const vendorShape = pt.shape({
name: pt.string.isRequired,
hostnames: pt.arrayOf(pt.string).isRequired,
faviconUrl: pt.string,
});

// Eventually we will dynamically extract vendor data, but for now it's
// hard-coded.
const VENDORS = [
{
name: 'Amazon',
hostnames: ['amazon.com', 'www.amazon.com', 'smile.amazon.com'],
faviconUrl: 'https://www.amazon.com/favicon.ico',
},
{
name: 'Best Buy',
hostnames: ['bestbuy.com', 'www.bestbuy.com'],
faviconUrl: 'https://www.bestbuy.com/favicon.ico',
},
{
name: 'eBay',
hostnames: ['ebay.com', 'www.ebay.com'],
faviconUrl: 'https://www.ebay.com/favicon.ico',
},
{
name: 'The Home Depot',
hostnames: ['homedepot.com', 'www.homedepot.com'],
faviconUrl: 'https://www.homedepot.com/favicon.ico',
},
{
name: 'Walmart',
hostnames: ['walmart.com', 'www.walmart.com'],
faviconUrl: 'https://www.walmart.com/favicon.ico',
},
{
name: 'mkelly Test',
hostnames: ['mkelly.me', 'www.mkelly.me'],
faviconUrl: '',
},
];

// Selectors

export function getVendor(state, url) {
const hostname = new URL(url).hostname;
return VENDORS.find(vendor => vendor.hostnames.includes(hostname));
}

0 comments on commit 9813ba8

Please sign in to comment.