You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by db...@apache.org on 2015/09/10 00:39:27 UTC

docs commit: Improve live reload workflow when working on plugin changes. Tweak title and description meta tags Add sortBy parameter to the plugin search URL Fixes improperly encoded URL when there are multiple platform filters Improperly encoded URLs on

Repository: cordova-docs
Updated Branches:
  refs/heads/cordova-website 946e53c8b -> 71a05a677


Improve live reload workflow when working on plugin changes.
Tweak title and description meta tags
Add sortBy parameter to the plugin search URL
Fixes improperly encoded URL when there are multiple platform filters
Improperly encoded URLs on Plugins page fix
Minor fixes to plugins page reloading in gulpfile
This closes #355.


Project: http://git-wip-us.apache.org/repos/asf/cordova-docs/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-docs/commit/71a05a67
Tree: http://git-wip-us.apache.org/repos/asf/cordova-docs/tree/71a05a67
Diff: http://git-wip-us.apache.org/repos/asf/cordova-docs/diff/71a05a67

Branch: refs/heads/cordova-website
Commit: 71a05a67742eb14cf47d7afda7b9a669622a39ef
Parents: 946e53c
Author: Nikhil Khandelwal <ni...@microsoft.com>
Authored: Tue Sep 8 17:55:04 2015 -0700
Committer: Dmitry Blotsky <dm...@gmail.com>
Committed: Wed Sep 9 15:38:31 2015 -0700

----------------------------------------------------------------------
 gulpfile.js                         |   5 +-
 www/plugins/index.html              |   3 +-
 www/static/plugins/SortCriteria.js  |   6 ++
 www/static/plugins/app.js           | 155 +++++++++++++++++++------------
 www/static/plugins/plugin.jsx       |  13 ---
 www/static/plugins/sortdropdown.jsx |   7 +-
 6 files changed, 108 insertions(+), 81 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-docs/blob/71a05a67/gulpfile.js
----------------------------------------------------------------------
diff --git a/gulpfile.js b/gulpfile.js
index d482639..e019bad 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -204,7 +204,6 @@ gulp.task("sass", function() {
 });
 
 gulp.task("plugins", function() {
-
     if (prod) {
         process.env.NODE_ENV = "production";
     }
@@ -224,7 +223,8 @@ gulp.task("plugins", function() {
     }
 
     return stream
-
+        .pipe(gulp.dest(JS_DIR.replace(SOURCE_DIR, out_dir)))
+        .pipe(browsersync.reload({stream: true}))
         // NOTE:
         //      adding YAML front matter at the end
         //      so that uglify doesn't screw it up
@@ -234,7 +234,6 @@ gulp.task("plugins", function() {
         //           minified JS has some things that look like
         //           Liquid tags, so we replace them manually
         .pipe(replace("){{", "){ {"))
-
         .pipe(gulp.dest(JS_DIR));
 });
 

http://git-wip-us.apache.org/repos/asf/cordova-docs/blob/71a05a67/www/plugins/index.html
----------------------------------------------------------------------
diff --git a/www/plugins/index.html b/www/plugins/index.html
index 460b69c..8a6c142 100644
--- a/www/plugins/index.html
+++ b/www/plugins/index.html
@@ -1,7 +1,8 @@
 ---
 layout: cordova
-title: Apache Cordova Plugins
+title: Apache Cordova Plugin Search
 plugins_tab: true
+description: Search here for Apache Cordova plugins published on NPM.
 ---
 
 <!-- REMOVE THIS LINK BEFORE PUBLISHING.  This is just for IntelliSense while coding -->

http://git-wip-us.apache.org/repos/asf/cordova-docs/blob/71a05a67/www/static/plugins/SortCriteria.js
----------------------------------------------------------------------
diff --git a/www/static/plugins/SortCriteria.js b/www/static/plugins/SortCriteria.js
new file mode 100644
index 0000000..a50a990
--- /dev/null
+++ b/www/static/plugins/SortCriteria.js
@@ -0,0 +1,6 @@
+var SortCriteria = {
+    Quality: "Quality",
+    RecentlyUpdated: "Recently Updated",
+    Downloads: "Downloads"
+}
+module.exports = SortCriteria;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-docs/blob/71a05a67/www/static/plugins/app.js
----------------------------------------------------------------------
diff --git a/www/static/plugins/app.js b/www/static/plugins/app.js
index f29f7fc..f02e163 100755
--- a/www/static/plugins/app.js
+++ b/www/static/plugins/app.js
@@ -3,7 +3,8 @@ var React           = window.React = require('react'), // assign it to window fo
     PluginList      = require('./pluginlist.jsx'),
     PlatformButton  = require('./platformbutton.jsx')
     App             = {},
-    SortDropdown = require('./sortdropdown.jsx');
+    SortDropdown = require('./sortdropdown.jsx'),
+    SortCriteria = require('./SortCriteria');
 
 var INPUT_DELAY = 500; // in milliseconds
 
@@ -13,12 +14,11 @@ var Constants = {
     NpmSearchInitialSize: 500
 }
 
-window.addEventListener('popstate', function(e) {
-    if(e.state) {
-        var appInstance = React.render(<App />, document.getElementById('container'));
-        appInstance.loadFilterText(e.state.filterText);
-    }
-});
+var UrlParameters = {
+    SortBy: 'sortBy',
+    Query: 'q',
+    Platfroms: 'platforms',
+}
 
 var App = React.createClass({
     getInitialState: function() {
@@ -26,17 +26,21 @@ var App = React.createClass({
         staticFilters['platforms'] = [];
         staticFilters['authors'] = [];
         staticFilters['licenses'] = [];
-        var platforms = App.getURLParameter('platforms');
+        var platforms = App.getURLParameter(UrlParameters.Platfroms);
         if(platforms) {
             staticFilters['platforms'] = staticFilters['platforms'].concat(platforms.split(','));
         }
-        var q = App.getURLParameter('q');
+        var q = App.getURLParameter(UrlParameters.Query);
+        var sortBy = App.getURLParameter(UrlParameters.SortBy);
+        if (!sortBy) {
+            sortBy = SortCriteria.Quality;
+        }
         var state = {
             plugins: [],
             placeHolderText: 'Loading...',
             searchResults: [],
             staticFilters: staticFilters,
-            sortCriteria: "Quality",
+            sortCriteria: sortBy,
             downloadsReceived: false
         }
 
@@ -49,17 +53,18 @@ var App = React.createClass({
         return state;
     },
     handleUserInput: function(filterText) {
+        var self = this;
         /* We receive events for all inputs, so make sure text changed */
         if(this.state.filterText !== filterText) {
             /* Routing logic */
             var platformFilters = this.state.staticFilters["platforms"];
             delay(function(){
-                App.updateURL(filterText, platformFilters);
+                App.updateURL(filterText, platformFilters, self.state.sortCriteria);
             }, INPUT_DELAY);
 
             this.setState({
                 filterText: filterText,
-                searchResults: App.filterPlugins(this.state.plugins, filterText, this.state.staticFilters)
+                searchResults: App.filterPlugins(self.state.plugins, filterText, self.state.staticFilters)
             });
         }
     },
@@ -74,7 +79,7 @@ var App = React.createClass({
             }
 
             delay(function(){
-                App.updateURL(previousState.filterText, previousState.staticFilters['platforms']);
+                App.updateURL(previousState.filterText, previousState.staticFilters['platforms'], previousState.sortCriteria);
             }, INPUT_DELAY);
 
             return {
@@ -87,6 +92,9 @@ var App = React.createClass({
     setSort: function(sort) {
         this.setState(function(previousState, currentProps) {
             App.sortPlugins(previousState.plugins, sort)
+             delay(function(){
+                App.updateURL(previousState.filterText, previousState.staticFilters['platforms'], previousState.sortCriteria);
+            }, INPUT_DELAY);
             return {
                 plugins: previousState.plugins,
                 searchResults: App.filterPlugins(previousState.plugins, this.state.filterText, this.state.staticFilters),
@@ -94,18 +102,29 @@ var App = React.createClass({
             }
         });
     },
-    loadFilterText : function(filterText) {
-        this.setState(function(previousState, currentProps) {
-            return {
-                filterText: filterText,
-                plugins: previousState.plugins
-            };
-        });
-    },
     statics: {
+        appendURLParameter : function(qs, urlParameter) {
+            if(!qs) {
+                qs = '?' + urlParameter + '=';
+            } else {
+                qs = qs + '&' + urlParameter + '=';
+            }
+            return qs;
+        },
         getURLParameter : function(name) {
-            return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(location.search)
-                ||[,""])[1].replace(/\+/g, '%20'))||null;
+                try {
+                    return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(location.search)
+                        ||[,""])[1].replace(/\+/g, '%20'))||null;
+                } catch(error) {
+                    // Improperly encoded URLs are ignored
+                    if (error instanceof URIError) {
+                        window.history.replaceState({}, "", "./");
+                        return null;
+                    }
+
+                    // Throw other errors back out
+                    throw error;
+                }
         },
         shallowCopy: function(src) {
             var dst = {};
@@ -218,7 +237,7 @@ var App = React.createClass({
                 }
             }
             switch(criteria) {
-                case 'Downloads':
+                case SortCriteria.Downloads:
                     plugins.sort(function(p1, p2) {
                         if(!p1.downloadCount) {
                             return 1;
@@ -231,7 +250,7 @@ var App = React.createClass({
                         return p2.downloadCount - p1.downloadCount;
                     });
                     break;
-                case 'Recently Updated':
+                case SortCriteria.RecentlyUpdated:
                     plugins.sort(function(p1, p2) {
                         if(p2.modified === p1.modified) {
                             return compareName(p1, p2);
@@ -239,7 +258,7 @@ var App = React.createClass({
                         return p1.modified - p2.modified;
                     });
                     break;
-                case 'Quality':
+                case SortCriteria.Quality:
                 default:
                     plugins.sort(function(p1, p2) {
                         if(p2.rating === p1.rating) {
@@ -251,28 +270,27 @@ var App = React.createClass({
             }
             return plugins;
         },
-        updateURL: function(filterText, platformFilters) {
-            var query = "?";
+        updateURL: function(filterText, platformFilters, sortCriteria) {
+            var query = '';
             var stateObj = {};
             if(filterText) {
                 var filterTextLowerCase = filterText;
-                query = "?q=" + filterTextLowerCase;
+                query = App.appendURLParameter(query, UrlParameters.Query);
+                query += encodeURIComponent(filterTextLowerCase);
                 stateObj.filterText = filterTextLowerCase;
             }
 
             if(platformFilters.length > 0) {
-                if(query === "?") {
-                    query = "?platforms=";
-                } else {
-                    query = query + "&platforms=";
-                }
-                platformFilters.forEach(function(platform) {
-                    query = query + platform + ",";
-                });
-                query = query.slice(0, query.length - 1);
+                query = App.appendURLParameter(query, UrlParameters.Platfroms);
+                query += encodeURIComponent(platformFilters.join());
                 stateObj.platforms = platformFilters;
             }
 
+            if(sortCriteria !== SortCriteria.Quality) {
+                query = App.appendURLParameter(query, UrlParameters.SortBy);
+                query += encodeURIComponent(sortCriteria);
+                stateObj.sortBy = sortCriteria;
+            }
             window.history.replaceState(stateObj, "", query);
             ga('send', 'pageview', '/index.html' + query);
         },
@@ -286,43 +304,54 @@ var App = React.createClass({
             queryHost = "http://npmsearch.com/query",
             queryFields = "fields=name,keywords,license,description,author,modified,homepage,version,rating",
             queryKeywords = "q=keywords:%22ecosystem:cordova%22",
-            queryInitialSize = Constants.NpmSearchInitialSize;
+            queryInitialSize = Constants.NpmSearchInitialSize,
+            baseUrl = queryHost + "?" + queryFields + "&" + queryKeywords + "&sort=rating:desc";
 
-        xhrRequest(queryHost + "?" + queryFields + "&" + queryKeywords + "&size=" + queryInitialSize + "&start=0", function(xhrResult) {
+        xhrRequest(baseUrl + "&size=" + queryInitialSize + "&start=0", function(xhrResult) {
             plugins = xhrResult.results;
             pluginCount = xhrResult.total;
             if (pluginCount <= queryInitialSize) {
                 processPlugins.bind(self, officialPlugins, plugins)();
             } else {
-                xhrRequest(queryHost + "?" + queryFields + "&" + queryKeywords + "&size=" + (pluginCount - queryInitialSize) + "&start=" + queryInitialSize, function(xhrResult) {
+                xhrRequest(baseUrl + "&size=" + (pluginCount - queryInitialSize) + "&start=" + queryInitialSize, function(xhrResult) {
                         plugins = [].concat(plugins, xhrResult.results);
                         processPlugins.bind(self, officialPlugins, plugins)();
                 }, function() { console.log('xhr err'); });
             }
         }, function() { console.log('xhr err'); });
 
-        var getDownloadCount = function(plugins, that) {
+        var getDownloadCount = function(plugins) {
             var packageNames = "";
-            for(var index=0; index < plugins.length; index++) {
+            var downloadCountRequests = [];
+            for(var index = 0; index < plugins.length; index++) {
                 packageNames += plugins[index].name + ",";
-                if(index % Constants.DownloadCountBatch === 0 || index === plugins.length -1) {
-                    xhrRequest("https://api.npmjs.org/downloads/point/last-month/" + packageNames, function(xhrResult) {
-                        for(var j = 0; j < plugins.length; j++) {
-                            if(xhrResult[plugins[j].name]) {
-                                plugins[j] = App.shallowCopy(plugins[j]);
-                                plugins[j].downloadCount = xhrResult[plugins[j].name].downloads;
-                            }
-                        }
 
-                        that.setState({
-                            plugins: plugins,
-                            searchResults: App.filterPlugins(plugins, this.state.filterText, this.state.staticFilters),
-                            downloadsReceived: true
-                        });
-                    }.bind(self), function() { console.log('xhr err'); });
+                if(index % Constants.DownloadCountBatch === 0 || index === plugins.length - 1) {
+                    downloadCountRequests.push($.getJSON("https://api.npmjs.org/downloads/point/last-month/" + packageNames));
                     packageNames = "";
                 }
             }
+            // When all the download count requests return - we can populate the plugins and sort them
+            $.when.apply($, downloadCountRequests).done(function() {
+                for(var i = 0; i < arguments.length; i ++) {
+                    var xhrResult = arguments[i][0];
+                    for(var j = 0; j < plugins.length; j++) {
+                        if(xhrResult[plugins[j].name]) {
+                            plugins[j] = App.shallowCopy(plugins[j]);
+                            plugins[j].downloadCount = xhrResult[plugins[j].name].downloads;
+                        }
+                    }
+                }
+                if(self.state.sortCriteria === SortCriteria.Downloads) {
+                    App.sortPlugins(plugins, self.state.sortCriteria);
+                }
+                self.setState({
+                    plugins: plugins,
+                    searchResults: App.filterPlugins(plugins, self.state.filterText, self.state.staticFilters),
+                    downloadsReceived: true
+                });
+            })
+            .fail( function() { console.log('xhr err'); });
         }
 
         function processPlugins(officialPlugins, plugins) {
@@ -357,11 +386,15 @@ var App = React.createClass({
                 plugins[i].modified = Math.ceil((dateNow - new Date(plugins[i].modified)) / oneDay);
             };
 
-            // Initial sort is always on quality
-            plugins = App.sortPlugins(plugins, 'Quality');
+            // Initial sort cannot be on downloads as download counts have not been populated.
+            if (this.state.sortCriteria !== SortCriteria.Downloads) {
+                plugins = App.sortPlugins(plugins, this.state.sortCriteria);
+            } else {
+                plugins = App.sortPlugins(plugins, SortCriteria.Quality);
+            }
 
             if (this.isMounted()) {
-                var q = App.getURLParameter('q');
+                var q = App.getURLParameter(UrlParameters.Query);
                 if(q) {
                     this.setState({
                         plugins: plugins,
@@ -377,7 +410,7 @@ var App = React.createClass({
                         searchResults: App.filterPlugins(plugins, '', this.state.staticFilters)
                     });
                 }
-                getDownloadCount(plugins,this);
+                getDownloadCount(plugins);
             }
         }
     },

http://git-wip-us.apache.org/repos/asf/cordova-docs/blob/71a05a67/www/static/plugins/plugin.jsx
----------------------------------------------------------------------
diff --git a/www/static/plugins/plugin.jsx b/www/static/plugins/plugin.jsx
index 347e5b6..2f3e457 100755
--- a/www/static/plugins/plugin.jsx
+++ b/www/static/plugins/plugin.jsx
@@ -21,14 +21,6 @@ var Plugin = React.createClass({
         if(!this.props.plugin) {
             // Empty card with loading wheel
             return (
-                // <li>
-                //     <div className="pluginCard">
-                //         <div style={{ textAlign: 'center', height: 10 + "rem"}}>
-                //             <span style={{ display: 'inline-block', height: 100 + "%", verticalAlign: 'middle'}} />
-                //             <img style={{verticalAlign: 'middle'}} src="img/loading.gif" />
-                //         </div>
-                //     </div>
-                // </li>
                 <div className="container plugin-results-result">
                     <div className="row">
                         <div className="col-sm-9">
@@ -47,11 +39,6 @@ var Plugin = React.createClass({
         var copyIcon;
         var npmLink = 'https://www.npmjs.com/package/' + this.props.plugin.name;
 
-        var classes = classNames({
-            'pluginCard': true,
-            'featuredPlugin': this.props.plugin.isOfficial
-        });
-
         if(this.props.plugin.downloadCount) {
             var downloadCount = this.props.plugin.downloadCount.toLocaleString();
             downloadField = <p className="downloads"><strong>{downloadCount}</strong> downloads last month</p>;

http://git-wip-us.apache.org/repos/asf/cordova-docs/blob/71a05a67/www/static/plugins/sortdropdown.jsx
----------------------------------------------------------------------
diff --git a/www/static/plugins/sortdropdown.jsx b/www/static/plugins/sortdropdown.jsx
index a8f57fa..f02ff55 100755
--- a/www/static/plugins/sortdropdown.jsx
+++ b/www/static/plugins/sortdropdown.jsx
@@ -1,12 +1,13 @@
 var React = require('react');
 var SortButton = require('./sortbutton.jsx');
+var SortCriteria = require('./SortCriteria');
 
 var SortDropdown = React.createClass({
     render: function() {
         var downloadsButton;
 
         if(this.props.downloadsEnabled) {
-            downloadsButton = <SortButton criteria="Downloads"/>;
+            downloadsButton = <SortButton criteria={SortCriteria.Downloads}/>;
         }
         return (
             <div className="dropdown plugins-sort-dropdown">
@@ -15,8 +16,8 @@ var SortDropdown = React.createClass({
                     <span className="caret"></span>
                 </button>
                 <ul className="dropdown-menu" aria-labelledby="dropdownMenu1">
-                    <SortButton criteria="Quality"/>
-                    <SortButton criteria="Recently Updated"/>
+                    <SortButton criteria={SortCriteria.Quality}/>
+                    <SortButton criteria={SortCriteria.RecentlyUpdated}/>
                     {downloadsButton}
                 </ul>
             </div>


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org