Commit 0b8fa0e5 authored by Becca Hughes's avatar Becca Hughes Committed by Commit Bot

Reland "Reland "[Media Feeds] Add feed items to WebUI""

This is a reland of 25e37730

The fix is to loosen the assertion on the time fields
which have a different format on win7.

Original change's description:
> Reland "[Media Feeds] Add feed items to WebUI"
>
> This is a reland of 0bbf0f94
>
> Original change's description:
> > [Media Feeds] Add feed items to WebUI
> >
> > This adds the feed items to the WebUI. You
> > can select a feed to show the content.
> >
> > BUG=1058187
> >
> > Change-Id: I5051f77b68cb3da6710a547d50109cb95a7b890f
> > Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2118758
> > Commit-Queue: Becca Hughes <beccahughes@chromium.org>
> > Reviewed-by: Tommy Steimel <steimel@chromium.org>
> > Cr-Commit-Position: refs/heads/master@{#753441}
>
> Bug: 1058187
> Change-Id: I7ec8a25ba03d192341e6d02eccfba991b4156504
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2121450
> Reviewed-by: Tommy Steimel <steimel@chromium.org>
> Commit-Queue: Becca Hughes <beccahughes@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#753712}

Bug: 1058187
Change-Id: I69f0f6dbe336d7a46b2c3d2e4e251256d37390d5
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2124630Reviewed-by: default avatarTommy Steimel <steimel@chromium.org>
Commit-Queue: Becca Hughes <beccahughes@chromium.org>
Cr-Commit-Position: refs/heads/master@{#754202}
parent 8cb28c67
......@@ -80,7 +80,7 @@ cr.define('cr.ui', function() {
key = k;
});
this.delegate_.insertDataField(td, data, key);
this.delegate_.insertDataField(td, data, key, dataRow);
tr.appendChild(td);
});
});
......@@ -103,8 +103,10 @@ cr.define('cr.ui', function() {
* @param {Element} td
* @param {?Object} data
* @param {string} key
* @param {Object} dataRow This is the row itself in case we need extra
* data to render the field.
*/
insertDataField(td, data, key) {}
insertDataField(td, data, key, dataRow) {}
/**
* Compares two objects based on |sortKey|.
......
......@@ -124,6 +124,8 @@
</th>
<th data-key="logos">
Logos
<th data-key="actions">
Actions
</th>
</tr>
</thead>
......@@ -131,22 +133,71 @@
</tbody>
</table>
<template id="datarow">
<tr>
<td class="id-cell"></td>
<td class="url-cell"></td>
<td></td>
<td class="last-discovery-time-cell"></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</template>
<div id="feed-content" style="display:none;">
<hr>
<h2>Feed Contents: <span id="current-feed"></span></h2>
<table id="feed-items-table">
<thead>
<tr>
<th sort-key="type" class="sort-column" sort-reverse>
Type
</th>
<th sort-key="name">
Name
</th>
<th sort-key="author">
Author
</th>
<th sort-key="datePublished">
Date Published
</th>
<th sort-key="isFamilyFriendly">
Family Friendly
</th>
<th sort-key="actionStatus">
Action Status
</th>
<th sort-key="action.url">
Action URL
</th>
<th sort-key="action.startTime">
Action Start Time (secs)
</th>
<th sort-key="interactionCounters">
Interaction Counters
</th>
<th sort-key="contentRatings">
Content Ratings
</th>
<th sort-key="genre">
Genre
</th>
<th sort-key="live">
Live Details
</th>
<th sort-key="tvEpisode">
TV Episode
</th>
<th sort-key="playNextCandidate">
Play Next Candidate
</th>
<th sort-key="identifiers">
Identifiers
</th>
<th sort-key="shownCount">
Shown Count
</th>
<th sort-key="clicked">
Clicked
</th>
<th sort-key="images">
Images
</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</body>
</html>
......@@ -11,10 +11,16 @@ function whenPageIsPopulatedForTest() {
return mediaFeedsPageIsPopulatedResolver.promise;
}
const mediaFeedItemsPageIsPopulatedResolver = new PromiseResolver();
function whenFeedTableIsPopulatedForTest() {
return mediaFeedItemsPageIsPopulatedResolver.promise;
}
(function() {
let delegate = null;
let feedsTable = null;
let feedItemsTable = null;
let store = null;
/** @implements {cr.ui.MediaDataTableDelegate} */
......@@ -25,8 +31,28 @@ class MediaFeedsTableDelegate {
* @param {Element} td
* @param {?Object} data
* @param {string} key
* @param {Object} dataRow
*/
insertDataField(td, data, key) {
insertDataField(td, data, key, dataRow) {
if (key == 'actions') {
const a = document.createElement('a');
a.href = '#feed-content';
a.textContent = 'Show Contents';
td.appendChild(a);
a.addEventListener('click', () => {
store.getItemsForMediaFeed(dataRow.id).then(response => {
feedItemsTable.setData(response.items);
// Show the feed items section.
$('current-feed').textContent = dataRow.url.url;
$('feed-content').style.display = 'block';
mediaFeedItemsPageIsPopulatedResolver.resolve();
});
});
}
if (data === undefined || data === null) {
return;
}
......@@ -36,11 +62,11 @@ class MediaFeedsTableDelegate {
td.textContent = data.url;
} else if (
key === 'lastDiscoveryTime' || key === 'lastFetchTime' ||
key === 'cacheExpiryTime') {
key === 'cacheExpiryTime' || key === 'datePublished') {
// Format a mojo time.
td.textContent =
convertMojoTimeToJS(/** @type {mojoBase.mojom.Time} */ (data))
.toString();
.toLocaleString();
} else if (key === 'userStatus') {
// Format a FeedUserStatus.
if (data == mediaFeeds.mojom.FeedUserStatus.kAuto) {
......@@ -74,7 +100,7 @@ class MediaFeedsTableDelegate {
td.textContent =
contentTypes.length === 0 ? 'None' : contentTypes.join(',');
} else if (key === 'logos') {
} else if (key === 'logos' || key === 'images') {
// Format an array of mojo media images.
data.forEach((image) => {
const a = document.createElement('a');
......@@ -84,6 +110,129 @@ class MediaFeedsTableDelegate {
td.appendChild(a);
td.appendChild(document.createElement('br'));
});
} else if (key == 'type') {
// Format a MediaFeedItemType.
switch (parseInt(data, 10)) {
case mediaFeeds.mojom.MediaFeedItemType.kVideo:
td.textContent = 'Video';
break;
case mediaFeeds.mojom.MediaFeedItemType.kTVSeries:
td.textContent = 'TV Series';
break;
case mediaFeeds.mojom.MediaFeedItemType.kMovie:
td.textContent = 'Movie';
break;
}
} else if (key == 'isFamilyFriendly' || key == 'clicked') {
// Format a boolean.
td.textContent = data ? 'Yes' : 'No';
} else if (key == 'actionStatus') {
// Format a MediaFeedItemActionStatus.
switch (parseInt(data, 10)) {
case mediaFeeds.mojom.MediaFeedItemActionStatus.kUnknown:
td.textContent = 'Unknown';
break;
case mediaFeeds.mojom.MediaFeedItemActionStatus.kActive:
td.textContent = 'Active';
break;
case mediaFeeds.mojom.MediaFeedItemActionStatus.kPotential:
td.textContent = 'Potential';
break;
case mediaFeeds.mojom.MediaFeedItemActionStatus.kCompleted:
td.textContent = 'Completed';
break;
}
} else if (key == 'startTime') {
// Format a start time.
td.textContent =
timeDeltaToSeconds(/** @type {mojoBase.mojom.TimeDelta} */ (data));
} else if (key == 'interactionCounters') {
// Format interaction counters.
const counters = [];
Object.keys(data).forEach((key) => {
let keyString = '';
switch (parseInt(key, 10)) {
case mediaFeeds.mojom.InteractionCounterType.kWatch:
keyString = 'Watch';
break;
case mediaFeeds.mojom.InteractionCounterType.kLike:
keyString = 'Like';
break;
case mediaFeeds.mojom.InteractionCounterType.kDislike:
keyString = 'Dislike';
break;
}
counters.push(keyString + '=' + data[key]);
});
td.textContent = counters.join(' ');
} else if (key == 'contentRatings') {
// Format content ratings.
const ratings = [];
data.forEach((rating) => {
ratings.push(rating.agency + ' ' + rating.value);
});
td.textContent = ratings.join(', ');
} else if (key == 'author') {
// Format a mojom author.
const a = document.createElement('a');
a.href = data.url;
a.textContent = data.name;
a.target = '_blank';
td.appendChild(a);
} else if (key == 'name' || key == 'genre') {
// Format a mojo string16.
td.textContent =
decodeString16(/** @type {mojoBase.mojom.String16} */ (data));
} else if (key == 'live') {
// Format LiveDetails.
td.textContent = 'Live';
if (data.startTime) {
td.textContent += ' ' +
'StartTime=' +
convertMojoTimeToJS(
/** @type {mojoBase.mojom.Time} */ (data.startTime))
.toLocaleString();
}
if (data.endTime) {
td.textContent += ' ' +
'EndTime=' +
convertMojoTimeToJS(
/** @type {mojoBase.mojom.Time} */ (data.endTime))
.toLocaleString();
}
} else if (key == 'tvEpisode') {
// Format a TV Episode.
td.textContent = data.name + ' EpisodeNumber=' + data.episodeNumber +
' SeasonNumber=' + data.seasonNumber + ' ' +
formatIdentifiers(/** @type {Array<mediaFeeds.mojom.Identifier>} */ (
data.identifiers));
} else if (key == 'playNextCandidate') {
// Format a Play Next Candidate.
td.textContent = data.name + ' EpisodeNumber=' + data.episodeNumber +
' SeasonNumber=' + data.seasonNumber + ' ' +
formatIdentifiers(
/** @type {Array<mediaFeeds.mojom.Identifier>} */ (
data.identifiers)) +
' ActionURL=' + data.action.url.url;
if (data.action.startTime) {
td.textContent +=
' ActionStartTimeSecs=' + timeDeltaToSeconds(data.action.startTime);
}
td.textContent += ' DurationSecs=' + timeDeltaToSeconds(data.duration);
} else if (key == 'identifiers') {
// Format identifiers.
td.textContent = formatIdentifiers(
/** @type {Array<mediaFeeds.mojom.Identifier>} */ (data));
} else {
td.textContent = data;
}
......@@ -121,6 +270,57 @@ class MediaFeedsTableDelegate {
}
}
/**
* Convert a time delta to seconds.
* @param {mojoBase.mojom.TimeDelta} timeDelta
* @returns {number}
*/
function timeDeltaToSeconds(timeDelta) {
return timeDelta.microseconds / 1000 / 1000;
}
/**
* Formats an array of identifiers for display.
* @param {Array<mediaFeeds.mojom.Identifier>} mojoIdentifiers
* @returns {string}
*/
function formatIdentifiers(mojoIdentifiers) {
const identifiers = [];
mojoIdentifiers.forEach((identifier) => {
let keyString = '';
switch (identifier.type) {
case mediaFeeds.mojom.Identifier_Type.kTMSRootId:
keyString = 'TMSRootId';
break;
case mediaFeeds.mojom.Identifier_Type.kTMSId:
keyString = 'TMSId';
break;
case mediaFeeds.mojom.Identifier_Type.kPartnerId:
keyString = 'PartnerId';
break;
}
identifiers.push(keyString + '=' + identifier.value);
});
return identifiers.join(' ');
}
/**
* Parses utf16 coded string.
* @param {?mojoBase.mojom.String16} arr
* @return {string}
*/
function decodeString16(arr) {
if (arr == null) {
return '';
}
return arr.data.map(ch => String.fromCodePoint(ch)).join('');
}
/**
* Converts a mojo time to a JS time.
* @param {mojoBase.mojom.Time} mojoTime
......@@ -160,6 +360,7 @@ document.addEventListener('DOMContentLoaded', () => {
delegate = new MediaFeedsTableDelegate();
feedsTable = new cr.ui.MediaDataTable($('feeds-table'), delegate);
feedItemsTable = new cr.ui.MediaDataTable($('feed-items-table'), delegate);
updateFeedsTable();
......
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