Skip to content

Conversation

emarchiori
Copy link
Contributor

amp-document-recommendations

Initial minimal extension for feedback and for incremental implementation. Settled on temporary name, avoiding infinite-scroll as UX currently has recommendations in between to create separation.

This PL does:

  • Load documents using the MultidocManager after the current doc
  • Show recommendations that use A2A linking between documents, to provide a natural break
  • Export MultidocManager so that it can be used by this extension

This PL does not:

  • Implement everything in the I2I
  • Include tests yet (waiting for feedback on the approach)
  • Manage any edge-cases (e.g. fixed position elements) or error-cases
  • Have a final UI

Related-to #12945

cc/ @aghassemi @peterjosling

@googlebot
Copy link

We found a Contributor License Agreement for you (the sender of this pull request), but were unable to find agreements for the commit author(s). If you authored these, maybe you used a different email address in the git commits than was used to sign the CLA (login here to double check)? If these were authored by someone else, then they will need to sign a CLA as well, and confirm that they're okay with these being contributed to Google.
In order to pass this check, please resolve this problem and have the pull request author add another comment and the bot will run again. If the bot doesn't comment, it means it doesn't think anything has changed.

@googlebot
Copy link

CLAs look good, thanks!

@googlebot googlebot added cla: yes and removed cla: no labels Feb 1, 2018
* limitations under the License.
*/

i-amp-document-recommendations {}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no tag called i-amp-document-recommendations right? I think this can be removed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.


i-amp-document-recommendations {}

.i-amp-document-recommendations {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

naming convention is i-amphtml-component-name for private CSS classes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

i-amp-document-recommendations {}

.i-amp-document-recommendations {
background: white;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: use hex

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

*/

/** @const */
const MAX_ARTICLES = 2;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: varibales after imports

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

constructor(element) {
super(element);

this.element.classList.add('i-amp-document-recommendations');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move to buildCallback

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

this.element.classList.add('i-amp-document-recommendations');

// TODO(emarchiori): Consider using a service instead of singleton.
if (this.win.CONTENT_DISCOVERY) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume this is simply a flag so that the component is only rendered once? If so, just having it be a variable outside of class (e.g. at extension level) would be better for now until this becomes a window level service.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct. Done.

return true;
}

appendDivision_() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

jsdocs for all methods.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

this.nextArticle_++;

Services.xhrFor(this.win)
.fetchDocument(next.ampUrl, {})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to pass {} since it is optional.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

appendArticleLinks_(from) {
const doc = this.win.document;
let article = from;
const viewer = Services.viewerForDoc(this.getAmpDoc());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do in constructor and keep this.viewer_

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

const next = this.config_.recommendations[article];
article++;

const articleHolder = doc.createElement('div');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use button for A11Y, otherwise need to handle taxIndex and enter/space activation manually.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.


this.config_ = assertConfig(configJson);

return this.mutateElement(() => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Other components (amp-list, amp-date-picker) make XHR requests for their content from the layoutCallback - probably makes sense for this too?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@aghassemi
Copy link
Contributor

@emarchiori @peterjosling Please ping me on this PR when ready for the final look. Thanks!

* @const
* TODO(emarchiori): Make this a configurable parameter.
*/
const SEPARATPOR_RECOS = 3;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: SEPARATOR

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

}

.i-amphtml-reco-holder-article {
padding-top:10px;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: space between colon and value (for each line in this block)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.


/** @override */
isLayoutSupported(layout) {
return layout == Layout.CONTAINER;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: ===

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Keeping == for consistency with other extensions and rest of the code.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we had a long discussions about this in the team :) although style guides says ===, we are sticking with ==

{
"recommendations": [
{
"image": "http://localhost:8000/examples/img/hero@1x.jpg",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove http://localhost:8000 and just have these as absolute paths ("image": "/examples/img/hero@1x.jpg", etc.) The host/port can be overridden.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@emarchiori emarchiori force-pushed the document-recommendations branch from 634e553 to b4c2f57 Compare February 26, 2018 09:07
Copy link
Contributor

@aghassemi aghassemi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

few nits and one request for checking that experiment is enabled in buildCallback.

}

/** @override */
buildCallback() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

needs a

    if (!isExperimentOn(this.getWin(), TAG)) {
      user.warn('Experiment %s is not turned on.', TAG);
      return;
    }

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Used an assert, for consistency with other experiments.

background: #FFFFFF;
}

.amp-document-recommendations-division {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: keep public css class on top of the CSS file

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.


/** @override */
isLayoutSupported(layout) {
return layout == Layout.CONTAINER;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we had a long discussions about this in the team :) although style guides says ===, we are sticking with ==

@aghassemi aghassemi changed the title Minimal document-level infinite-scroll extension Minimal (experimental) document-level infinite-scroll extension Feb 27, 2018
@aghassemi aghassemi merged commit 4d3dd44 into ampproject:master Feb 27, 2018
@aghassemi
Copy link
Contributor

@emarchiori @peterjosling merged.

tags: { # <amp-document-recommendations>
html_format: AMP
tag_name: "AMP-DOCUMENT-RECOMMENDATIONS"
mandatory_parent: "BODY"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason this needs to have parent of body and why it must be the last child of body?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a restriction that we might want to remove or relax it in the future, but forcing those two conditions reduces potentially unexpected behaviors (e.g. no footer on the first article as there are others in between, but the following article having a footer in the middle as it does not load other articles recursively).

Adding support to hide things like footer in all but the last article and headers in all but the first can probably led to the relaxation of this in followup changes.

Any particular concerns with this restrictions?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it means no other component can also be last in the body. It makes this component have some significance among all components. @aghassemi thoughts?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spoke with @aghassemi to clarify intent. Thank you.

@emarchiori emarchiori deleted the document-recommendations branch February 28, 2018 13:49
honeybadgerdontcare added a commit that referenced this pull request Mar 8, 2018
* Revision bump for #13184

* Revision bump for #13480#13665

* Revision bump for #13752

* Revision bump for #13773

* Removing AMP-YOUTUBE tag from AMP4EMAIL validator spec.

* A unit test that ensures no extensions are accidentally added to EXPERIMENTAL amp html format.

* Implement amp-story-auto-ads validation rules.

* Revision bump for #13846 and #13816

* Revision bump for #13883
RanAbram pushed a commit to RanAbram/amphtml that referenced this pull request Mar 12, 2018
* Revision bump for ampproject#13184

* Revision bump for ampproject#13480ampproject#13665

* Revision bump for ampproject#13752

* Revision bump for ampproject#13773

* Removing AMP-YOUTUBE tag from AMP4EMAIL validator spec.

* A unit test that ensures no extensions are accidentally added to EXPERIMENTAL amp html format.

* Implement amp-story-auto-ads validation rules.

* Revision bump for ampproject#13846 and ampproject#13816

* Revision bump for ampproject#13883
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants