nitweb: rewrite catalog frontend
authorAlexandre Terrasa <alexandre@moz-code.org>
Tue, 15 Aug 2017 20:55:32 +0000 (16:55 -0400)
committerAlexandre Terrasa <alexandre@moz-code.org>
Tue, 26 Sep 2017 15:10:05 +0000 (11:10 -0400)
Signed-off-by: Alexandre Terrasa <alexandre@moz-code.org>

share/nitweb/directives/contributor-list.html [deleted file]
share/nitweb/directives/entity/card.html
share/nitweb/javascripts/catalog.js
share/nitweb/javascripts/nitweb.js
share/nitweb/views/catalog/by_tags.html [deleted file]
share/nitweb/views/catalog/highlighted.html [deleted file]
share/nitweb/views/catalog/index.html
share/nitweb/views/catalog/most_required.html [deleted file]
share/nitweb/views/catalog/person.html [new file with mode: 0644]
share/nitweb/views/catalog/tag.html [new file with mode: 0644]

diff --git a/share/nitweb/directives/contributor-list.html b/share/nitweb/directives/contributor-list.html
deleted file mode 100644 (file)
index a46cce9..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-<div ng-if='listContributors.length > 0'>
-       <h3 id={{listId}}>
-               <span>{{listTitle}}</span>
-       </h3>
-       <ul class='list-unstyled user-list'>
-               <li ng-repeat='contributor in listContributors'>
-                       <img class='avatar' src="https://secure.gravatar.com/avatar/{{contributor.hash}}?size=20&amp;default=retro">
-                       {{contributor.name}}
-               </li>
-       </ul>
-</div>
index 9f85113..18675a0 100644 (file)
@@ -2,10 +2,34 @@
        <div class='card-left text-center'>
                <entity-tag mentity='mentity' />
        </div>
-       <div class='card-body'>
+       <div class='card-body' ng-if='mentity.class_name == "MPackage"' style='width: 75%'>
                <h5 class='card-heading'>
                        <entity-signature mentity='mentity' />
+                       <small ng-if='mentity.class_name == "MPackage"'>
+                               <span ng-repeat='tag in mentity.metadata.tags'>
+                                       <a ui-sref='tag({id: tag})' class='text-muted'>{{tag}}</a>
+                                       <span ng-if='!$last'>,</span>
+                               </span>
+                       </small>
                </h5>
                <span class='synopsis' ng-bind-html='mentity.mdoc.html_synopsis' />
        </div>
+       <div class='card-body' ng-if='mentity.class_name != "MPackage"'>
+               <h5 class='card-heading'>
+                       <entity-signature mentity='mentity' />
+               </h5>
+               <span class='synopsis' ng-bind-html='mentity.mdoc.html_synopsis' />
+       </div>
+       <div class='card-right' ng-if='mentity.class_name == "MPackage"' style='width: 25%'>
+               <span ng-repeat='maintainer in mentity.metadata.maintainers'>
+                       <img class='avatar' src='https://secure.gravatar.com/avatar/{{maintainer.gravatar}}?size=14&amp;default=retro' />
+                       <a ui-sref='person({id: maintainer.name})'>{{maintainer.name}}</a>
+               </span>
+               <br>
+               <span ng-if='mentity.metadata.license'>
+                       <span class='text-muted'>
+                               <a href='http://opensource.org/licenses/{{mentity.license}}' class='text-muted'>{{mentity.metadata.license}}</a>
+                       </span>
+               </span>
+       </div>
 </div>
index 922ae1e..2667db3 100644 (file)
  */
 
 (function() {
-       angular
-               .module('catalog', [])
-
-               .config(function($stateProvider, $locationProvider) {
-                       $stateProvider
-                               .state('catalog', {
-                                       url: '/',
-                                       templateUrl: 'views/catalog/index.html',
-                                       controller: 'CatalogCtrl',
-                                       controllerAs: 'vm',
-                                       abstract: true
-                               })
-                               .state('catalog.highlighted', {
-                                       url: '',
-                                       templateUrl: 'views/catalog/highlighted.html',
-                                       controller: 'CatalogHighlightedCtrl',
-                                       controllerAs: 'vm'
-                               })
-                               .state('catalog.required', {
-                                       url: 'required',
-                                       templateUrl: 'views/catalog/most_required.html',
-                                       controller: 'CatalogRequiredCtrl',
-                                       controllerAs: 'vm'
-                               })
-                               .state('catalog.tags', {
-                                       url: 'tags',
-                                       templateUrl: 'views/catalog/by_tags.html',
-                                       controller: 'CatalogTagsCtrl',
-                                       controllerAs: 'vm'
-                               })
-               })
-
-               .factory('Catalog', [ '$http', function($http) {
-                       return {
-                               loadHightlighted: function(cb, cbErr) {
-                                       $http.get('/api/catalog/highlighted')
-                                               .success(cb)
-                                               .error(cbErr);
-                               },
-
-                               loadMostRequired: function(cb, cbErr) {
-                                       $http.get('/api/catalog/required')
-                                               .success(cb)
-                                               .error(cbErr);
-                               },
-
-                               loadByTags: function(cb, cbErr) {
-                                       $http.get('/api/catalog/bytags')
-                                               .success(cb)
-                                               .error(cbErr);
-                               },
-
-                               loadStats: function(cb, cbErr) {
-                                       $http.get('/api/catalog/stats')
-                                               .success(cb)
-                                               .error(cbErr);
-                               },
-
-                               loadContributors: function(cb, cbErr) {
-                                       $http.get('/api/catalog/contributors')
-                                               .success(cb)
-                                               .error(cbErr);
-                               },
+       angular.module('catalog', [])
+
+       /* Router */
+
+       .config(function($stateProvider, $locationProvider) {
+               $stateProvider
+                       .state('catalog', {
+                               url: '/?p&n',
+                               controller: 'CatalogCtrl',
+                               controllerAs: 'vm',
+                               templateUrl: 'views/catalog/index.html',
+                               resolve: {
+                                       packages: function(Catalog, $q, $stateParams, $state) {
+                                               var d = $q.defer();
+                                               var page = $stateParams.p ? $stateParams.p : 1;
+                                               var limit = $stateParams.n ? $stateParams.n : 10;
+                                               Catalog.packages(page, limit, d.resolve,
+                                                       function(err) {
+                                                               $state.go('404', null, { location: false })
+                                                       });
+                                               return d.promise;
+                                       },
+                                       tags: function(Catalog, $q, $state) {
+                                               var d = $q.defer();
+                                               Catalog.tags(d.resolve,
+                                                       function(err) {
+                                                               $state.go('404', null, { location: false })
+                                                       });
+                                               return d.promise;
+                                       },
+                                       stats: function(Catalog, $q, $state) {
+                                               var d = $q.defer();
+                                               Catalog.stats(d.resolve,
+                                                       function(err) {
+                                                               $state.go('404', null, { location: false })
+                                                       });
+                                               return d.promise;
+
+                                       }
+                               }
+                       })
+                       .state('person', {
+                               url: '/person/:id?p1&n1&p2&n2',
+                               controller: 'PersonCtrl',
+                               controllerAs: 'vm',
+                               templateUrl: 'views/catalog/person.html',
+                               resolve: {
+                                       person: function(Catalog, $q, $stateParams, $state) {
+                                               var d = $q.defer();
+                                               Catalog.person($stateParams.id, d.resolve,
+                                               function(err) {
+                                                       $state.go('404', null, { location: false })
+                                               });
+                                               return d.promise;
+                                       },
+                                       maintaining: function(Catalog, $q, $stateParams, $state) {
+                                               var d = $q.defer();
+                                               var p1 = $stateParams.p2 ? $stateParams.p1 : 1;
+                                               var n1 = $stateParams.n2 ? $stateParams.n1 : 10;
+                                               Catalog.personMaintaining($stateParams.id, p1, n1, d.resolve,
+                                                       function(err) {
+                                                               $state.go('404', null, { location: false })
+                                                       });
+                                               return d.promise;
+                                       },
+                                       contributing: function(Catalog, $q, $stateParams, $state) {
+                                               var d = $q.defer();
+                                               var p2 = $stateParams.p2 ? $stateParams.p2 : 1;
+                                               var n2 = $stateParams.n2 ? $stateParams.n2 : 10;
+                                               Catalog.personContributing($stateParams.id, p2, n2, d.resolve,
+                                                       function(err) {
+                                                               $state.go('404', null, { location: false })
+                                                       });
+                                               return d.promise;
+
+                                       }
+                               }
+                       })
+                       .state('tag', {
+                               url: '/tag/:id?p&n',
+                               controller: 'TagCtrl',
+                               controllerAs: 'vm',
+                               templateUrl: 'views/catalog/tag.html',
+                               resolve: {
+                                       tag: function(Catalog, $q, $stateParams, $state) {
+                                               var d = $q.defer();
+                                               var page = $stateParams.p ? $stateParams.p : 1;
+                                               var limit = $stateParams.l ? $stateParams.l : 10;
+                                               Catalog.tag($stateParams.id, page, limit, d.resolve,
+                                                       function() {
+                                                               $state.go('404', null, { location: false })
+                                                       });
+                                               return d.promise;
+                                       }
+                               }
+                       })
+       })
+
+       /* Factories */
+
+       .factory('Catalog', [ '$http', function($http) {
+               return {
+                       stats: function(cb, cbErr) {
+                               $http.get('/api/catalog/stats')
+                                       .success(cb)
+                                       .error(cbErr);
+                       },
+                       packages: function(p, n, cb, cbErr) {
+                               $http.get('/api/catalog/packages?p=' + p + '&n=' + n)
+                                       .success(cb)
+                                       .error(cbErr);
+                       },
+                       tags: function(cb, cbErr) {
+                               $http.get('/api/catalog/tags')
+                                       .success(cb)
+                                       .error(cbErr);
+                       },
+                       person: function(id, cb, cbErr) {
+                               $http.get('/api/catalog/person/' + id)
+                                       .success(cb)
+                                       .error(cbErr);
+                       },
+                       personMaintaining: function(id, p, n, cb, cbErr) {
+                               $http.get('/api/catalog/person/' + id + '/maintaining?p=' + p + '&n=' + n)
+                                       .success(cb)
+                                       .error(cbErr);
+                       },
+                       personContributing: function(id, p, n, cb, cbErr) {
+                               $http.get('/api/catalog/person/' + id + '/contributing?p=' + p + '&n=' + n)
+                                       .success(cb)
+                                       .error(cbErr);
+                       },
+                       tag: function(id, p, n, cb, cbErr) {
+                               $http.get('/api/catalog/tag/' + id + '?p=' + p + '&n=' + n)
+                                       .success(cb)
+                                       .error(cbErr);
                        }
-               }])
-
-               .controller('CatalogCtrl', function(Catalog) {
-                       var vm = this;
-
-                       Catalog.loadContributors(
-                               function(data) {
-                                       vm.contributors = data;
-                               }, function(err) {
-                                       vm.error = err;
-                               });
-
-                       Catalog.loadStats(
-                               function(data) {
-                                       vm.stats = data;
-                               }, function(err) {
-                                       vm.error = err;
-                               });
-               })
-
-               .controller('CatalogHighlightedCtrl', function(Catalog) {
-                       var vm = this;
+               };
+       }])
 
-                       Catalog.loadHightlighted(
-                               function(data) {
-                                       vm.highlighted = data;
-                               }, function(err) {
-                                       vm.error = err;
-                               });
-               })
+       /* Controllers */
 
-               .controller('CatalogRequiredCtrl', function(Catalog) {
-                       var vm = this;
+       .controller('CatalogCtrl', function($scope, $state, packages, tags, stats) {
+               var vm = this;
+               vm.packages = packages;
+               vm.tags = tags;
+               vm.stats = stats;
 
-                       Catalog.loadMostRequired(
-                               function(data) {
-                                       vm.required = data;
-                               }, function(err) {
-                                       vm.error = err;
-                               });
+               $scope.$on('change-page', function(e, page, limit) {
+                       $state.go('catalog', {p: page, l: limit});
                })
+       })
 
-               .controller('CatalogTagsCtrl', function(Catalog, $anchorScroll, $location) {
-                       var vm = this;
+       .controller('PersonCtrl', function($scope, $state, $stateParams, person, maintaining, contributing) {
+               var vm = this;
+               vm.person = person;
+               vm.maintaining = maintaining;
+               vm.contributing = contributing;
 
-                       Catalog.loadByTags(
-                               function(data) {
-                                       vm.bytags = data;
-                               }, function(err) {
-                                       vm.error = err;
-                               });
+               var p1 = $stateParams.p1 ? $stateParams.p1 : 1;
+               var n1 = $stateParams.n1 ? $stateParams.n1 : 10;
+               var p2 = $stateParams.p2 ? $stateParams.p2 : 1;
+               var n2 = $stateParams.n2 ? $stateParams.n2 : 10;
 
+               $scope.$on('change-page1', function(e, page, limit) {
+                       $state.go('person', {id: $stateParams.id, p1: page, n1: limit, p2: p2, n2: n2});
+               })
 
-                       vm.scrollTo = function(hash) {
-                               $location.hash(hash);
-                               $anchorScroll();
-                       }
+               $scope.$on('change-page2', function(e, page, limit) {
+                       $state.go('person', {id: $stateParams.id, p1: p1, n1: n1, p2: page, n2: limit});
                })
+       })
+
+       .controller('TagCtrl', function($state, $scope, tag) {
+               var vm = this;
+               vm.tag = tag;
 
-               .directive('contributorList', function(Model) {
-                       return {
-                               restrict: 'E',
-                               scope: {
-                                       listId: '@',
-                                       listTitle: '@',
-                                       listContributors: '='
-                               },
-                               templateUrl: '/directives/contributor-list.html'
-                       };
+               $scope.$on('change-page', function(e, page, limit) {
+                       $state.go('tag', {id: vm.tag.tag, p: page, l: limit});
                })
+       })
 })();
index 10e17fa..1de3f69 100644 (file)
                cfpLoadingBarProvider.includeSpinner = false;
        }])
 
-       .run(['$anchorScroll', function($anchorScroll) {
+       .run(function($rootScope, $anchorScroll) {
                $anchorScroll.yOffset = 80;
-       }])
+               $rootScope.$on('$stateChangeSuccess', function() {
+                 $anchorScroll();
+               });
+       })
 
        .config(function($stateProvider, $locationProvider) {
                $stateProvider
diff --git a/share/nitweb/views/catalog/by_tags.html b/share/nitweb/views/catalog/by_tags.html
deleted file mode 100644 (file)
index 31ca905..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-<div>
-       <h3>Tags</h3>
-       <div class='container-fluid'>
-               <div class='col-xs-3' ng-repeat='(tag, packages) in vm.bytags'>
-                       <span class='badge'>{{packages.length}}</span>
-                       <a ng-click='vm.scrollTo(tag)'>{{tag}}</a>
-               </div>
-       </div>
-       <div ng-repeat='(tag, packages) in vm.bytags'>
-               <entity-list list-id='{{tag}}' list-title='{{tag}}'
-                       list-entities='packages'
-                       list-object-filter='{}' />
-       </div>
-</div>
diff --git a/share/nitweb/views/catalog/highlighted.html b/share/nitweb/views/catalog/highlighted.html
deleted file mode 100644 (file)
index 5607bd5..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-<div>
-       <entity-list list-title='Highlighted packages'
-               list-entities='vm.highlighted'
-               list-object-filter='{}' />
-</div>
index 877db4a..2333a0a 100644 (file)
@@ -1,47 +1,35 @@
-<div class='container-fluid'>
+<div class='container'>
        <div class='page-header'>
                <h2>Welcome to NitWeb!</h2>
                <p class='text-muted'>The Nit knowledge base.</p>
        </div>
 
-       <ul class='nav nav-tabs' role='tablist'>
-               <li role='presentation' ui-sref-active='active'>
-                       <a ui-sref='catalog.highlighted'>
-                               <span class='glyphicon glyphicon-book'/> Highlighed
-                       </a>
-               </li>
-               <li role='presentation' ui-sref-active='active'>
-                       <a ui-sref='catalog.required'>
-                               <span class='glyphicon glyphicon-book'/> Most required
-                       </a>
-               </li>
-               <li role='presentation' ui-sref-active='active'>
-                       <a ui-sref='catalog.tags'>
-                               <span class='glyphicon glyphicon-book'/> By tags
-                       </a>
-               </li>
-       </ul>
-       <table class='table'>
-               <tr>
-                       <td ng-repeat='(key, value) in vm.stats'>
-                               <h5><strong>{{value}}</strong>&nbsp;<span>{{key}}</span></h5>
-                       </td>
-               </tr>
-       </table>
+       <div ng-if='vm.stats' class='container-fluid no-padding'>
+               <span ng-repeat='(key, value) in vm.stats' class='text-muted small'>
+                       <strong>{{value}}</strong>&nbsp;<span>{{key}}</span>
+                       &nbsp;
+               </span>
+       </div>
+       <hr/>
 
-       <div class='container-fluid'>
-               <div class='col-xs-9'>
-                       <div class='tab-content'>
-                               <div role='tabpanel' class='tab-pane fade in active'>
-                                       <ui-view />
-                               </div>
+       <div class='col-md-3 col-md-push-9 no-padding' ng-if='vm.tags'>
+               <h2>Tags</h2>
+               <div class='container-fluid no-padding'>
+                       <div class='col-xs-3 col-md-12' ng-repeat='(tag, packages) in vm.tags'>
+                               <span class='badge'>{{packages}}</span>
+                               <a ui-sref='tag({id: tag})'>{{tag}}</a>
                        </div>
                </div>
-               <div class='col-xs-3'>
-                       <contributor-list list-title='Maintainers'
-                                       list-contributors='vm.contributors.maintainers' />
-                       <contributor-list list-title='Contributors'
-                                       list-contributors='vm.contributors.contributors' />
+               <hr/>
+       </div>
+
+       <div class='col-md-9 col-md-pull-3 no-padding'>
+               <h2>Packages</h2>
+               <div class='card-list'>
+                       <entity-card mentity='package' ng-repeat='package in vm.packages.results' />
+               </div>
+               <div class='container text-center' ng-if='vm.packages'>
+                       <ui-pagination pagination='vm.packages'/>
                </div>
        </div>
 </div>
diff --git a/share/nitweb/views/catalog/most_required.html b/share/nitweb/views/catalog/most_required.html
deleted file mode 100644 (file)
index 93bf2e1..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-<div>
-       <entity-list list-title='Most required'
-               list-entities='vm.required'
-               list-object-filter='{}' />
-</div>
diff --git a/share/nitweb/views/catalog/person.html b/share/nitweb/views/catalog/person.html
new file mode 100644 (file)
index 0000000..433b73d
--- /dev/null
@@ -0,0 +1,33 @@
+<div class='container'>
+       <div class='col-xs-2 no-padding'>
+               <img class='avatar' style='width:100%; max-width:100px' src='https://secure.gravatar.com/avatar/{{vm.person.gravatar}}?size=100&amp;default=retro' />
+       </div>
+       <div class='col-xs-10'>
+               <h1>
+                       {{vm.person.name}}<br>
+                       <small>{{vm.person.email}}</small>
+               </h1>
+       </div>
+       <hr/>
+</div>
+<br><br>
+<div class='container'>
+       <div ng-if='vm.maintaining.results.length > 0'>
+               <h3 id='maintaining'>{{vm.maintaining.total}} maintained projects</h3>
+               <div class='card-list'>
+                       <entity-card mentity='package' ng-repeat='package in vm.maintaining.results' />
+               </div>
+               <div class='container text-center' ng-if='vm.maintaining'>
+                       <ui-pagination pagination='vm.maintaining' suffix='1'/>
+               </div>
+       </div>
+       <div ng-if='vm.contributing.results.length > 0'>
+               <h3 id='contributing'>{{vm.contributing.total}} contributed projects</h3>
+               <div class='card-list'>
+                       <entity-card mentity='package' ng-repeat='package in vm.contributing.results' />
+               </div>
+               <div class='container text-center' ng-if='vm.contributing'>
+                       <ui-pagination pagination='vm.contributing' suffix='2' />
+               </div>
+       </div>
+</div>
diff --git a/share/nitweb/views/catalog/tag.html b/share/nitweb/views/catalog/tag.html
new file mode 100644 (file)
index 0000000..6c0a37e
--- /dev/null
@@ -0,0 +1,16 @@
+<div class='container'>
+       <h1>
+               {{vm.tag.tag}}
+               <small>{{vm.tag.packages.total}} packages</small>
+       </h1>
+       <hr/>
+
+       <div class='container-fluid no-padding' ng-if='vm.tag.packages.results.length > 0'>
+               <div class='card-list'>
+                       <entity-card mentity='package' ng-repeat='package in vm.tag.packages.results' />
+               </div>
+               <div class='container text-center' ng-if='vm.tag.packages'>
+                       <ui-pagination pagination='vm.tag.packages'/>
+               </div>
+       </div>
+</div>