jenkins-bot has submitted this change and it was merged.

Change subject: Add a module that renders cards
......................................................................


Add a module that renders cards

How to use:
mw.loader.using( 'ext.cards.gateway' ).done( function() {
    var gateway = new mw.cards.CardsGateway( { api: new mw.Api() } );

    // '1' and '2' are page titles, while 200 is the desired thumbnail width
    gateway.getCards( ['1', '2'], 200 ).done( function( cards ) {
        // insert cards.getHtml() into the DOM
    } );
} );

Dependency: I8bce3777366cf774b16bc0c1bde7bf8cf9d6496d
Bug: T114393
Change-Id: I0ba9e348867b8edb5e0c01ac0628c3a918f4c4f2
---
M extension.json
D resources/.gitkeep
A resources/CardsGateway.js
A resources/init.js
A resources/view/Card.js
A resources/view/CardList.js
A resources/view/card.hogan
A resources/view/cards.hogan
A resources/view/noimage.png
A resources/view/noimage.svg
A resources/view/styles.less
11 files changed, 284 insertions(+), 0 deletions(-)

Approvals:
  Phuedx: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/extension.json b/extension.json
index 077c16b..a0f56b1 100644
--- a/extension.json
+++ b/extension.json
@@ -18,5 +18,55 @@
        },
        "Hooks": {
        },
+       "ResourceFileModulePaths": {
+               "localBasePath": "",
+               "remoteExtPath": "Cards"
+       },
+       "ResourceModules": {
+               "ext.cards.init": {
+                       "targets": [
+                               "mobile"
+                       ],
+                       "group": "other",
+                       "scripts": [
+                               "resources/init.js"
+                       ]
+               },
+               "ext.cards.view": {
+                       "targets": [
+                               "mobile"
+                       ],
+                       "group": "other",
+                       "dependencies": [
+                               "oojs",
+                               "mediawiki.Title",
+                               "mediawiki.template.hogan",
+                               "ext.cards.init"
+                       ],
+                       "scripts": [
+                               "resources/view/Card.js",
+                               "resources/view/CardList.js"
+                       ],
+                       "styles": [
+                               "resources/view/styles.less"
+                       ],
+                       "templates": {
+                               "card.hogan": "resources/view/card.hogan",
+                               "cards.hogan": "resources/view/cards.hogan"
+                       }
+               },
+               "ext.cards.gateway": {
+                       "targets": [
+                               "mobile"
+                       ],
+                       "group": "other",
+                       "dependencies": [
+                               "ext.cards.view"
+                       ],
+                       "scripts": [
+                               "resources/CardsGateway.js"
+                       ]
+               }
+       },
        "manifest_version": 1
 }
diff --git a/resources/.gitkeep b/resources/.gitkeep
deleted file mode 100644
index e69de29..0000000
--- a/resources/.gitkeep
+++ /dev/null
diff --git a/resources/CardsGateway.js b/resources/CardsGateway.js
new file mode 100644
index 0000000..44c6963
--- /dev/null
+++ b/resources/CardsGateway.js
@@ -0,0 +1,82 @@
+( function ( $ ) {
+       'use strict';
+
+       /**
+        * Default thumbnail width in pixels: 50px
+        * @readonly
+        */
+       var THUMB_WIDTH = 50,
+               Card = mw.cards.Card,
+               CardList = mw.cards.CardList;
+
+       /**
+        * Gateway for retrieving article info from the API and returning 
{mw.cards.CardList}
+        *
+        * @class
+        * @param {Object} options
+        * @param {mw.Api} options.api an Api to use.
+        */
+       mw.cards.CardsGateway = function ( options ) {
+               this.api = options.api;
+       };
+
+       OO.initClass( mw.cards.CardsGateway );
+
+       /**
+        *
+        * @param {String[]} articleTitles array of article titles
+        * @param {Number} [thumbWidth] Thumbnail width in pixels. Defaults to
+        *  {@link THUMB_WIDTH}
+        * @return {jQuery.Deferred} the result resolves with 
{mw.cards.CardList}
+        */
+       mw.cards.CardsGateway.prototype.getCards = function ( articleTitles, 
thumbWidth ) {
+               var article,
+                       cards = [],
+                       result = $.Deferred();
+
+               if ( !articleTitles.length ) {
+                       result.resolve( new CardList( cards ) );
+                       return result;
+               }
+
+               this.api.get( {
+                       action: 'query',
+                       prop: 'extracts|pageimages',
+                       explaintext: true,
+                       exlimit: articleTitles.length,
+                       exintro: true,
+                       exsentences: 1,
+                       pithumbsize: thumbWidth || THUMB_WIDTH,
+                       titles: articleTitles.join( '|' ),
+                       continue: ''
+               } ).done( function ( data ) {
+                       if ( data.query && data.query.pages ) {
+                               cards = $.map( data.query.pages, function ( 
page ) {
+                                       article = {
+                                               title: page.title,
+                                               url: ( new mw.Title( page.title 
) ).getUrl(),
+                                               hasThumbnail: false
+                                       };
+
+                                       if ( page.thumbnail ) {
+                                               article.hasThumbnail = true;
+                                               article.thumbnailUrl = 
page.thumbnail.source;
+                                               article.isThumbnailPortrait = 
page.thumbnail.height >= page.thumbnail.width;
+                                       }
+
+                                       if ( page.extract ) {
+                                               article.extract = page.extract;
+                                       }
+
+                                       return new Card( article );
+                               } );
+                       }
+                       result.resolve( new CardList( cards ) );
+               } ).fail( function () {
+                       result.resolve( new CardList( cards ) );
+               } );
+
+               return result;
+       };
+
+} )( jQuery );
diff --git a/resources/init.js b/resources/init.js
new file mode 100644
index 0000000..b552931
--- /dev/null
+++ b/resources/init.js
@@ -0,0 +1,9 @@
+( function () {
+       'use strict';
+
+       /**
+        * @class mw.cards
+        * @singleton
+        */
+       mw.cards = {};
+} )();
diff --git a/resources/view/Card.js b/resources/view/Card.js
new file mode 100644
index 0000000..3407b82
--- /dev/null
+++ b/resources/view/Card.js
@@ -0,0 +1,26 @@
+( function () {
+       'use strict';
+
+       /**
+        * View that handles a single article info
+        *
+        * @class
+        * @param {Object} article information, such as title, url, etc. about 
an article
+        */
+       mw.cards.Card = function ( article ) {
+               this.article = article;
+       };
+
+       OO.initClass( mw.cards.Card );
+
+       mw.cards.Card.prototype.template = mw.template.get( 'ext.cards.view', 
'card.hogan' );
+
+       /**
+        * Render the template and return HTML
+        *
+        * @return {String}
+        */
+       mw.cards.Card.prototype.getHtml = function () {
+               return this.template.render( this.article );
+       };
+} )();
diff --git a/resources/view/CardList.js b/resources/view/CardList.js
new file mode 100644
index 0000000..d509694
--- /dev/null
+++ b/resources/view/CardList.js
@@ -0,0 +1,36 @@
+( function () {
+       'use strict';
+
+       var Card = mw.cards.Card;
+
+       /**
+        * View that handles multiple {@link mw.cards.Card cards}
+        *
+        * @class
+        * @param {mw.cards.Card[]} cards
+        */
+       mw.cards.CardList = function ( cards ) {
+               this.cards = cards || [];
+       };
+
+       OO.initClass( mw.cards.CardList );
+
+       mw.cards.CardList.prototype.template = mw.template.get( 
'ext.cards.view', 'cards.hogan' );
+
+       /**
+        * Render the cards and return HTML
+        *
+        * @return {String}
+        */
+       mw.cards.CardList.prototype.getHtml = function () {
+               return this.template.render(
+                       {
+                               cards: this.cards
+                       },
+                       {
+                               card: Card.prototype.template
+                       }
+               );
+
+       };
+} )();
diff --git a/resources/view/card.hogan b/resources/view/card.hogan
new file mode 100644
index 0000000..c46f96c
--- /dev/null
+++ b/resources/view/card.hogan
@@ -0,0 +1,10 @@
+<li title="{{ title }}" class="ext-cards-page">
+       <a href="{{ url }}">
+               <div class="card-thumb {{# hasThumbnail }}{{# 
isThumbnailPortrait }}portrait{{/ isThumbnailPortrait }}{{^ isThumbnailPortrait 
}}landscape{{/ isThumbnailPortrait }}{{/ hasThumbnail }}"
+                         {{# hasThumbnail }}style="background-image: url( {{{ 
thumbnailUrl }}} )"{{/ hasThumbnail }}></div>
+               <h3>{{ title }}</h3>
+               {{# extract }}
+                       <div class="extract">{{ extract }}</div>
+               {{/ extract }}
+       </a>
+</li>
diff --git a/resources/view/cards.hogan b/resources/view/cards.hogan
new file mode 100644
index 0000000..149ec4c
--- /dev/null
+++ b/resources/view/cards.hogan
@@ -0,0 +1,9 @@
+{{# cards.length }}
+       <ul class="ext-cards-page-list">
+       {{# cards }}
+               {{# article }}
+                       {{> card }}
+               {{/ article }}
+       {{/ cards }}
+       </ul>
+{{/ cards.length }}
diff --git a/resources/view/noimage.png b/resources/view/noimage.png
new file mode 100644
index 0000000..60d16cd
--- /dev/null
+++ b/resources/view/noimage.png
Binary files differ
diff --git a/resources/view/noimage.svg b/resources/view/noimage.svg
new file mode 100644
index 0000000..dd09aac
--- /dev/null
+++ b/resources/view/noimage.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg"; viewBox="0 0 56 56" 
enable-background="new 0 0 56 56">
+    <path fill="#eee" d="M0 0h56v56h-56z"/>
+    <path fill="#999" d="M36.4 13.5h-18.6v24.9c0 1.4.9 2.3 2.3 
2.3h18.7v-25c.1-1.4-1-2.2-2.4-2.2zm-6.2 3.5h5.1v6.4h-5.1v-6.4zm-8.8 
0h6v1.8h-6v-1.8zm0 4.6h6v1.8h-6v-1.8zm0 
15.5v-1.8h13.8v1.8h-13.8zm13.8-4.5h-13.8v-1.8h13.8v1.8zm0-4.7h-13.8v-1.8h13.8v1.8z"/>
+</svg>
diff --git a/resources/view/styles.less b/resources/view/styles.less
new file mode 100644
index 0000000..e183612
--- /dev/null
+++ b/resources/view/styles.less
@@ -0,0 +1,57 @@
+@import "mediawiki.mixins";
+@import "mediawiki.ui/variables";
+
+@thumbWidth: 50px;
+
+.ext-cards-page-list {
+       border-top: 1px solid @colorGray14;
+       list-style: none;
+       overflow: hidden;
+
+       .ext-cards-page {
+               border-bottom: 1px solid @colorGray14;
+               box-sizing: border-box;
+               display: table;
+               margin: 0;
+               height: @thumbWidth;
+               padding: 5px 10px 5px ( @thumbWidth + 10px );
+               position: relative;
+               width: 100%;
+
+               a {
+                       display: table-cell;
+                       vertical-align: middle;
+               }
+       }
+
+       h3 {
+               margin: 0;
+               padding: 0;
+       }
+
+       .extract {
+               font-size: .8em;
+       }
+
+       .card-thumb {
+               background-color: @colorGray14;
+               .background-image-svg( 'noimage.svg', 'noimage.png' );
+               background-repeat: no-repeat;
+               background-position: center center;
+               left: 0;
+               height: 100%;
+               position: absolute;
+               top: 0;
+               width: @thumbWidth;
+
+               &.portrait {
+                       background-color: transparent;
+                       .background-size( auto, 100% );
+               }
+
+               &.landscape {
+                       background-color: transparent;
+                       .background-size( 100%, auto );
+               }
+       }
+}

-- 
To view, visit https://gerrit.wikimedia.org/r/246137
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I0ba9e348867b8edb5e0c01ac0628c3a918f4c4f2
Gerrit-PatchSet: 12
Gerrit-Project: mediawiki/extensions/Cards
Gerrit-Branch: master
Gerrit-Owner: Bmansurov <[email protected]>
Gerrit-Reviewer: Bmansurov <[email protected]>
Gerrit-Reviewer: Hashar <[email protected]>
Gerrit-Reviewer: Jdlrobson <[email protected]>
Gerrit-Reviewer: Jhobs <[email protected]>
Gerrit-Reviewer: Phuedx <[email protected]>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to