angular-strap bs-typeahead for organization
authorDobrica Pavlinusic <dpavlin@rot13.org>
Wed, 9 Jan 2013 17:09:01 +0000 (18:09 +0100)
committerDobrica Pavlinusic <dpavlin@rot13.org>
Wed, 9 Jan 2013 17:09:01 +0000 (18:09 +0100)
angular-server.pl
app/drzb2013.html.ep
app/js/app.js
app/js/controllers.js
app/js/services.js
app/partials/registration.html.ep

index 25fa407..bec44b8 100755 (executable)
@@ -177,12 +177,43 @@ any [ 'post' ] => '/data/:database/:entity' => sub {
 
 get '/:database/_design/:design/_view/:view' => sub {
        my $self = shift;
+       my $format = $self->param('format');
        my $url = join('/', $self->param('database'),'_design',$self->param('design'),'_view',$self->param('view') );
-       my $param = $self->req->url->query->clone->remove('callback')->to_string;
-       $url .= '?' . $param if $param;
+       if ( my $param = $self->req->url->query->clone->remove('callback')->remove('format')->to_string ) {
+               $url .= '?' . $param
+       }
        warn "CouchDB proxy $url";
-       _render_jsonp( $self, _couchdb_get($url));
+       my $json = _couchdb_get($url);
+       if ( $format eq 'key_array' ) { # array of keys sorted by value
+               $json->{rows} = [ map { $_->{key} } sort { $b->{value} <=> $a->{value} } @{ $json->{rows} } ];
+       }
+       _render_jsonp( $self, $json );
+};
+
+# http://showmetheco.de/articles/2010/10/adding-etag-caching-to-your-mojolicious-app.html
+
+hook after_dispatch => sub {
+       my $self = shift;
+
+       return unless $self->req->method eq 'GET';
+
+       my $body = $self->res->body;
+       return unless defined $body;
+
+       return if $self->res->headers->header('ETag');
+
+       my $our_etag = Mojo::ByteStream->new($body)->md5_sum;
+       $self->res->headers->header('ETag' => $our_etag);
+
+       my $browser_etag = $self->req->headers->header('If-None-Match');
+       return unless $browser_etag && $browser_etag eq $our_etag;
+
+       $self->app->log->info("HTTP cache hit ", dump( $self->req->url->to_string ), $our_etag );
+
+       $self->res->code(304);
+       $self->res->body('');
 };
 
+
 app->start;
 
index 712c77d..8ebdff2 100644 (file)
 <!--
   <div>Angular seed app: v<span app-version></span></div>
 -->
+  <script src="/lib/jquery/1.8.3/jquery.min.js"></script>
+  <script src="/lib/bootstrap/js/bootstrap.min.js"></script>
   <!-- In production use:
   <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.2/angular.min.js"></script>
   -->
   <script src="/lib/angular/angular.js"></script>
   <script src="/lib/angular/angular-resource.js"></script>
+  <script src="/lib/angular-strap/dist/angular-strap.min.js"></script>
   <script src="/js/app.js"></script>
   <script src="/js/services.js"></script>
   <script src="/js/controllers.js"></script>
index 5938a2b..03179c9 100644 (file)
@@ -2,7 +2,7 @@
 
 
 // Declare app level module which depends on filters, and services
-angular.module('myApp', ['myApp.filters', 'myApp.services', 'myApp.directives']).
+angular.module('myApp', ['myApp.filters', 'myApp.services', 'myApp.directives', '$strap.directives' ]).
   config(['$routeProvider', function($routeProvider) {
     $routeProvider.when('/registration/:registrationId', {templateUrl: 'partials/registration.html', controller: RegistrationCtrl});
     $routeProvider.when('/confirmation/:registrationId', {templateUrl: 'partials/confirmation.html', controller: RegistrationCtrl});
index f0e6d03..7c47eb8 100644 (file)
@@ -3,10 +3,11 @@
 /* Controllers */
 
 
-function RegistrationCtrl($scope, $log, Registration, $routeParams, $location, $route) {
+function RegistrationCtrl($scope, $log, Registration, $routeParams, $location, $route, View) {
 
        $scope.$routeParams = $routeParams;
        $scope.$location = $location;
+       $scope.organizations = [];
 
        $scope.update = function(registration) {
 
@@ -43,7 +44,24 @@ function RegistrationCtrl($scope, $log, Registration, $routeParams, $location, $
                }
 
                $log.info( $routeParams.registrationId );
+
+               $scope.view = new View();
+if(1){//FIXME
+               $scope.view.$get({ view: 'organizations' }, function(result) {
+                       $log.info('View organizations', result);
+                       angular.forEach( result.rows, function(value, key) {
+                               this.push( value.key ); // name of organization
+                       }, $scope.organizations );
+                       $log.info('organizations', $scope.organizations);
+               });
+}else{//FIXME
+               $scope.view.$key_array({ view: 'organizations' }, function(result) {
+                       $log.info('key_array', result);
+                       $scope.organizations = result.rows;
+                       $log.info('organizations', $scope.organizations);
+               });
        }
+}//FIXME
 
        $scope.$watch('user.registration_type', function( oldValue, newValue ) {
                $log.info("registration_type watch", oldValue, newValue );
index 04bc7db..c513978 100644 (file)
@@ -37,4 +37,10 @@ angular.module('myApp.services', [ 'ngResource' ]).
                return $resource('/data/:database/registration/:registrationId', { database: 'drzb2013v2' }, {
                        query: {method:'GET', params:{registraionId:'@id'}, isArray:true}
                });
+       }).
+       factory('View', function($resource) {
+               return $resource('/:database/_design/registration/_view/:view?group=true;format=:format', { database: 'drzb2013' }, {
+                       key_array: {method:'GET', params:{ format:'key_array' }, isArray:true}
+               });
+
        });
index 86404d7..34fd058 100644 (file)
@@ -61,7 +61,7 @@ hr => 'Registracija - kontakt podaci'
 </div>
 
 <div class="controls controls-row">
- <input class="my-input span10" ng-model="user.organization" placeholder="<%= $Organization %>" >
+ <input class="my-input span10" ng-model="user.organization" placeholder="<%= $Organization %>" bs-typeahead="organizations" data-items="10" >
 </div>
 
 % my $Address = locale en => 'Address', hr => 'Adresa';
@@ -113,7 +113,7 @@ en => 'Organization contact details',
 hr => 'Organizacija koja uplaćuje R-1 račun' %>
 </legend>
 
-<input class="my-input span10" ng-model="user.r1.organization" ng-required="user.r1.required" placeholder="<%= $Organization %>">
+<input class="my-input span10" ng-model="user.r1.organization" ng-required="user.r1.required" placeholder="<%= $Organization %>" bs-typeahead="organizations" >
 <input class="my-input span10" ng-model="user.r1.address" ng-required="user.r1.required" placeholder="<%= $Address %>">
 <input class="my-input span5" ng-model="user.r1.OIB" ng-required="user.r1.required" placeholder="OIB">
 
@@ -185,7 +185,7 @@ hr => 'Organizator simpozija' %>
 <div ng-repeat="person in work.persons" class="controls controls-row">
        <input class="span2 my-input" ng-model="person.firstname" placeholder="<%= $Name %>" ng-required="has_work" />
        <input class="span2 my-input" ng-model="person.surname"   placeholder="<%= $Surname %>" ng-required="has_work" />
-       <input class="span2 my-input" ng-model="person.organization" placeholder="<%= $Organization %>" >
+       <input class="span2 my-input" ng-model="person.organization" placeholder="<%= $Organization %>" bs-typeahead="organizations" >
        <input class="span2 my-input" ng-model="person.email" type="email" placeholder="<%= $Email %>" ng-required="has_work" />
        <a class="controls span1 btn btn-danger" href="" ng-click="removePerson(work.persons,person)"><%= locale en => 'delete', hr => 'obriši' %></a>
 </div>