authors table view
authorDobrica Pavlinusic <dpavlin@rot13.org>
Tue, 12 Mar 2013 22:35:37 +0000 (23:35 +0100)
committerDobrica Pavlinusic <dpavlin@rot13.org>
Tue, 12 Mar 2013 22:36:14 +0000 (23:36 +0100)
more general usage of View factory to display CouchDB view as table

angular-server.pl
app/drzb2013.html.ep
app/js/app.js
app/js/controllers.js
app/js/services.js.ep
app/partials/authors.html.ep [new file with mode: 0644]
test/unit/controllersSpec.js

index 0e38168..94c84ad 100755 (executable)
@@ -262,7 +262,29 @@ if ( doc.user.organization != '' ) {
 }
                                        }q|,
                                        reduce => q| function(keys,values,rereduce) { return sum(values); } |,
-                               }
+                               },
+                               authors => {
+                                       map => q|
+function(doc) {
+  if ( doc.work.persons ) {
+    doc.work.persons.forEach( function(person) {
+      emit(person.surname+person.firstname ,
+        person
+      );
+    });
+  }
+  if ( doc.work.symposium_works ) {
+    doc.work.symposium_works.forEach( function(work) {
+      work.persons.forEach( function(person) {
+        emit(person.surname+person.firstname ,
+          person
+        );
+      });
+    });
+  }
+}
+                                       |,
+                               },
                        }
                };
                $json = _couchdb_get($url)
@@ -271,6 +293,17 @@ if ( doc.user.organization != '' ) {
 
        if ( $format eq 'key_array' ) { # array of keys sorted by value
                $json->{rows} = [ map { $_->{key} } sort { $b->{value} <=> $a->{value} } @{ $json->{rows} } ];
+       } elsif ( $format eq 'key_distinct' ) {
+
+               my $found;
+               $json->{rows} = [ grep { $found->{ $_->{key} }++ == 1 } @{ $json->{rows} } ];
+               $json->{distinct_rows} = scalar @{ $json->{rows} };
+               warn "## distinct stats ", dump( $found );
+
+       } elsif ( $format ) {
+
+               die "unknown format: $format";
+
        }
 
        $view_cache->{$url}->{time} = time();
index 9d089fb..5211c5d 100644 (file)
@@ -47,6 +47,7 @@
   <ul class="nav">
     <li data-match-route="/registration"><a href="#/registration">registation</a></li>
     <li data-match-route="/list"><a href="#/list">list</a></li>
+    <li data-match-route="/authors"><a href="#/authors">authors</a></li>
     <li class="divider-vertical"></li>
   </ul>
   <div class="brand"><span app-version></span></div>
index 661be9e..22d056f 100644 (file)
@@ -10,5 +10,6 @@ angular.module('myApp', ['myApp.filters', 'myApp.services', 'myApp.directives',
     $routeProvider.when('/verified/:registrationId', {templateUrl: 'partials/verified.html', controller: RegistrationCtrl});
     $routeProvider.when('/review/:registrationId', {templateUrl: 'partials/review.html', controller: RegistrationCtrl});
     $routeProvider.when('/list', {templateUrl: 'partials/list.html', controller: ListCtrl});
+    $routeProvider.when('/authors', {templateUrl: 'partials/authors.html', controller: AuthorsCtrl});
     $routeProvider.otherwise({redirectTo: '/registration/'});
   }]);
index c7a043c..ab41a03 100644 (file)
@@ -7,9 +7,13 @@ function RegistrationCtrl($scope, $log, Registration, $routeParams, $location, $
        $scope.$routeParams = $routeParams;
        $scope.$location = $location;
        $scope.organizations = [];
-       View.getArrayPromise('organizations?group=true;format=key_array').then(function(data) {
-               $scope.organizations = data;
-               $log.info('organizations promise ', $scope.organizations);
+       View.getPromise('organizations?group=true;format=key_array').then(function(data) {
+               if ( angular.isArray(data.rows) ) {
+                       $scope.organizations = data.rows;
+                       $log.info('organizations promise ', $scope.organizations);
+               } else {
+                       $log.info('no rows in', data);
+               }
        });
        $scope.ValidStates = ValidStates();
 
@@ -331,3 +335,23 @@ function ListCtrl($scope, $log, Registration, RegistrationTypes, $filter, ValidS
 
 ListCtrl.$inject = [ '$scope', '$log', 'Registration', 'RegistrationTypes', '$filter', 'ValidStates' ];
 
+
+function AuthorsCtrl($scope, $log, View ) {
+       $scope.message = 'Loading data...';
+       $scope.ready = false;
+       View.getPromise('authors?format=key_distinct').then(function(data) {
+               if ( angular.isArray(data.rows) ) {
+                       $scope.data = data;
+                       $scope.authors = $scope.data.rows;
+                       $scope.ready = true;
+                       $log.info('authors promise ', data);
+               } else {
+                       $log.info('no rows in', data);
+                       $scope.message = 'No rows found';
+               }
+       });
+}
+
+AuthorsCtrl.$inject = [ '$scope', '$log', 'View' ];
+
+
index 0a94ae2..44e2a0b 100644 (file)
@@ -46,17 +46,18 @@ angular.module('myApp.services', [ 'ngResource' ]).
 
 /* http://jsfiddle.net/asgoth/7bNAd/ */
        factory('View', function($q, $http, $log) {
+
+               var deferred = $q.defer();
+
                return {
-                       getArrayPromise: function(view_url) {
+                       getPromise: function(view_url) {
                                var url = '/<%= $couchdb_database %>/_design/registration/_view/'+view_url+';callback=JSON_CALLBACK';
 
-                               var deferred = $q.defer();
-
                                $log.info('defer', url);
 
                                $http.jsonp(url).success(function(json) {
                                        $log.info('success', url);
-                                       deferred.resolve(json.rows);
+                                       deferred.resolve(json);
                                }).error(function(error) {
                                        $log.error('error', url, error );
                                        deferred.reject(error);
diff --git a/app/partials/authors.html.ep b/app/partials/authors.html.ep
new file mode 100644 (file)
index 0000000..d151365
--- /dev/null
@@ -0,0 +1,41 @@
+
+<div ng-show="! ready" class="alert alert-important">
+{{message}}
+</div>
+
+<form ng-controller="AuthorsCtrl" class="form-search" ng-show="ready">
+
+<fieldset>
+<legend>
+Authors
+</legend>
+
+<input class="my-lebel-input search-query" ng-model="search.$" label="Search">
+
+<a class="btn btn-invert" href="" ng-click="reset()">
+<i class="icon-remove"></i></a>
+
+<tt>{{search}}</tt>
+
+{{data.total_rows}} authors
+{{data.distinct_rows}} distinct
+
+</fieldset>
+
+<table ng-show="authors.length" class="table">
+<tr ng-repeat="author in authors | filter:search">
+<td>{{author.value.surname}}</td>
+<td>{{author.value.firstname}}</td>
+<td>{{author.value.organization}}</td>
+<td>{{author.value.email}}</td>
+</tr>
+</table>
+
+% if ( $lang =~ m/x-dev/ ) {
+<pre class="controls-row">
+{{authors}}
+</pre>
+% }
+
+</form>
+
index e0ad327..e7eb996 100644 (file)
@@ -73,3 +73,35 @@ describe('ListCtrl', function(){
        expect( scope.ValidStates ).toBeTruthy();
   });
 });
+
+
+describe('AuthorsCtrl', function(){
+  var scope, $httpBackend;
+
+  beforeEach(module('myApp'));
+
+  beforeEach(inject(function($injector) {
+    $httpBackend = $injector.get('$httpBackend');
+       $httpBackend.whenJSONP(/authors/).passThrough();
+  }));
+  afterEach(function() {
+         $httpBackend.verifyNoOutstandingExpectation();
+         $httpBackend.verifyNoOutstandingRequest();
+  });
+
+  beforeEach(inject(function($rootScope, $controller){
+    scope = $rootScope.$new();
+       var ctrl = $controller(AuthorsCtrl, { $scope: scope } );
+  }));
+
+
+  it('ready', function() {
+       $httpBackend.flush();
+       expect( scope.ready ).toBe( true );
+  });
+
+  it('data', function() {
+       $httpBackend.flush();
+       expect( scope.data ).toBeTruthy();
+  });
+});