CouchDB examples:
- couchdb-changes.pl - simple _changes feed watcher using Mojo::Client documented at
+ couchdb-changes.pl - simple _changes feed watcher using Mojo::UserAgent documented at
http://wiki.apache.org/couchdb/HTTP_database_API#Changes
use warnings;
use strict;
-use Mojo::Client;
+use Mojo::UserAgent;
use Data::Dump qw(dump);
use lib 'common/mojo/lib';
die "usage: $0 http://from/data/database/ http://to/data/database/\n"
unless $from && $to;
-my $client = Mojo::Client->new;
+my $client = Mojo::UserAgent->new;
my $got = $client->get( $from )->res->json;
warn "# from $from ",dump($got);
use Data::Dump qw(dump);
use Time::HiRes;
use Clone qw(clone);
+use Mojo::UserAgent;
sub new_uuid { Time::HiRes::time * 100000 }
# http://docs.getangular.com/REST.Basic
# http://angular.getangular.com/data
-my $couchdb = 'http://localhost:5984';
-my $client = Mojo::Client->new;
+my $couchdb = $ENV{COUCHDB} || 'http://localhost:5984';
+my $client = Mojo::UserAgent->new;
sub _couchdb_put {
my ( $url, $data ) = @_;
my $rev;
warn "# _couchdb_put $url = $json";
- $client->put( "$couchdb/$url" => $json => sub {
- my ($client,$tx) = @_;
- my ($message, $code) = $tx->error;
- my $response = $tx->res->json;
- warn "## response $code ",dump($response);
- if ($tx->error) {
- warn "ERROR $code $message";
- }
- return
- $rev = $response->{rev};
- })->process;
-
- warn "## rev = $rev";
- return $rev;
+ return $client->put( "$couchdb/$url" => $json)->res->json;
}
sub _couchdb_get {
$json->{'$id'} ||= $id; # make sure $id is in there
- my $rev = _couchdb_put "/$database/$entity.$id" => $json;
- $json->{_rev} = $rev;
+ my $new = _couchdb_put "/$database/$entity.$id" => $json;
+ warn "new: ",dump($new);
+ if ( $new->{ok} ) {
+ $json->{'_'.$_} = $new->{$_} foreach ( 'rev','id' );
+ } else {
+ warn "ERROR: ",dump($new);
+ $json->{error} = $new;
+ }
_render_jsonp( $self, $json );
};
_render_jsonp( $self, $docs )
};
+# app/resevations
+use Encode;
+use iCal::Parser;
+
+plugin 'proxy';
+
+get '/reservations/get/(*url)' => sub {
+ my $self = shift;
+
+ my $text = $client->get( 'http://' . $self->param('url') )->res->body;
+ warn "# get ", $self->param('url'), dump($text);
+
+ $text = decode( 'utf-8', $text );
+ $text =~ s{\\,}{,}gs;
+ $text =~ s{\\n}{ }gs;
+
+ my $c = iCal::Parser->new->parse_strings( $text );
+
+# warn "# iCal::Parser = ",dump($c);
+
+ my $ical = {
+ cal => $c->{cals}->[0], # FIXME assume single calendar
+ };
+
+ my $e = $c->{events};
+ my @events;
+
+ foreach my $yyyy ( sort keys %$e ) {
+ foreach my $mm ( sort keys %{ $e->{$yyyy} } ) {
+ foreach my $dd ( sort keys %{ $e->{$yyyy}->{$mm} } ) {
+ push @events, values %{ $e->{$yyyy}->{$mm}->{$dd} };
+ }
+ }
+ }
+
+ @events = map {
+ foreach my $check_slot ( qw(
+ DESCRIPTION
+ LOCATION
+ STATUS
+ SUMMARY
+ )) {
+ next unless exists $_->{$check_slot};
+ $_->{slots} = $1 if $_->{$check_slot} =~ m/(\d+)\s*mjesta/s;
+ }
+ $_;
+ } @events;
+
+ $ical->{events} = [ sort {
+ $a->{DTSTART} cmp $b->{DTSTART}
+ } @events ];
+
+ _render_jsonp( $self, $ical );
+};
+
+get '/reservations/events/:view_name' => sub {
+ my $self = shift;
+
+ my $view = _couchdb_get('/reservations/_design/events/_view/' . $self->param('view_name') . '?group=true');
+ my $hash;
+
+ if ( exists $view->{error} ) {
+ _couchdb_put "/reservations/_design/events", {
+ _id => '_design/events',
+ language => 'javascript',
+ views => {
+ submited => {
+ map => q|
+ function(doc) {
+ if ( doc.event && doc.event.UID ) emit(doc.event.UID, 1)
+ }
+ |,
+ reduce => q|_sum|,
+ }
+ }
+ };
+ }
+
+ _render_jsonp( $self, {} ) unless ref $view->{rows} eq 'ARRAY';
+
+ foreach my $row ( @{ $view->{rows} } ) {
+ $hash->{ $row->{key} } = $row->{value};
+ }
+
+ _render_jsonp( $self, $hash );
+};
+
+get '/_utils/script/(*url)' => sub { $_[0]->proxy_to( "$couchdb/_utils/script/" . $_[0]->param('url') , with_query_params => 1 ) };
+
app->start;
__DATA__
-Subproject commit c6b96c83cb1904ce1894e18d3bf553df651817bd
+Subproject commit a777d8d1952922f4f0289c892bbeb3808d000958
use lib 'common/mojo/lib';
-use Mojo::Client;
+use Mojo::UserAgent;
use Mojo::JSON;
my $url = 'http://localhost:5984/monitor/_changes?feed=continuous;include_docs=true;since=';
my $seq = 0;
-my $client = Mojo::Client->new;
+my $client = Mojo::UserAgent->new;
my $json = Mojo::JSON->new;
my $error;
use lib 'common/mojo/lib';
-use Mojo::Client;
+use Mojo::UserAgent;
use Mojo::JSON;
use Time::HiRes qw(time);
use Data::Dump qw(dump);
my $seq = 0;
-my $client = Mojo::Client->new;
+my $client = Mojo::UserAgent->new;
our $json = Mojo::JSON->new;
sub info { warn $_[0], " ",$json->encode($_[1]),$/ }
sub debug { info "# $_[0]", $_[1] }
--- /dev/null
+<!DOCTYPE HTML>
+<html xmlns:ng="http://angularjs.org">
+<head>
+<meta charset="utf-8">
+<!--
+<script src="angular.js" ng:autobind></script>
+-->
+<script src="http://code.angularjs.org/0.9.15/angular-0.9.15.min.js"
+ ng:autobind></script>
+
+<script>
+Calendar.$inject = ['$xhr', '$resource'];
+
+function Calendar($xhr,$resource){
+ console.info('Calendar');
+ var self = this;
+ $xhr("GET"
+ , "/reservations/get/www.google.com/calendar/ical/8tg8ecg285qshtp75813jktqa0%40group.calendar.google.com/private-b9d68b530fde2c6060979f8a05aa0865/basic.ics"
+ , function(code, response){
+ console.log('xhr calendar', code, response);
+ self.data = response;
+ }
+ );
+
+ var Reservation = $resource('/data/reservations/prijava/:id');
+ this.reservation = new Reservation();
+
+ this.load_submited = function() {
+ $xhr("GET"
+ , "/reservations/events/submited"
+ , function(code, response){
+ console.log('xhr submited', code, response);
+ self.submited = response;
+ }
+ );
+ }
+ this.load_submited();
+
+ self.reservation.status = 'event';
+
+ this.select_event = function(c) {
+ console.info('select_event', c);
+ self.reservation.event = c;
+ self.reservation.status = 'changed';
+ if (self.submited) self.reservation.slot_nr = ++self.submited[c.UID];
+ }
+
+ this.change_event = function() {
+ self.reservation.event = null;
+ self.reservation.status = 'event';
+ self.load_submited();
+ }
+
+ this.save_submission = function() {
+ if ( self.reservation && self.reservation.event ) {
+ console.info('submit save');
+ self.reservation.status = 'saved';
+ self.reservation.$save();
+ self.load_submited();
+ } else {
+ console.info('submit ignored');
+ }
+ }
+
+}
+
+// http://groups.google.com/group/angular/browse_thread/thread/af68afb22fd2d2ab/18fc5e3216a77e53?show_docid=18fc5e3216a77e53
+</script>
+
+<title>Reservations</title>
+
+<style>
+</style>
+
+</head>
+<body>
+
+<div ng:controller="Calendar">
+
+<h1>{{data.cal['X-WR-CALNAME']}}</h1>
+
+<div>{{data.cal['X-WR-CALDESC'] | html}}</div>
+
+<ul>
+<li ng:repeat="c in data.events" ng:show="reservation.status == 'event'">
+{{c.DTSTART}} - {{c.DTEND}}
+<a href="" ng:click="select_event(c)" ng:show="! reservation.event && c.UID != reservation.event.UID">{{c.SUMMARY}}</a>
+<b ng:show="reservation.event && reservation.event.UID == c.UID">{{c.SUMMARY}}</b>
+<em ng:show="submited[c.UID]">
+broj prijava: {{submited[c.UID]}}
+</em>
+<em ng:show="c.slots">/{{c.slots}}</em>
+<div>{{c.LOCATION}}</div>
+<div ng:show="c.DESCRIPTION">
+{{c.DESCRIPTION}}
+</div>
+</li>
+</ul>
+
+<div ng:show="reservation.error" style="background:#f88">{{reservation.error}}</div>
+
+<form ng:show="reservation.status != 'event'">
+
+<div ng:show="reservation.event" style="background: #ff8">
+Vaša <b>{{reservation.status}}</b> prijava za
+<b>{{reservation.event.SUMMARY}}</b>
+u terminu {{reservation.event.DTSTART}} u trajanju od {{reservation.event.hours}} sata
+<span ng:show="reservation.slot_nr">broj {{reservation.slot_nr}}</span>
+<span ng:show="reservation.saved">je spremljena.</span>
+<input type=button value="Potvrdi promjenu" ng:show="reservation.changed" ng:click="save_submission()">
+
+<a href="" ng:click="change_event()">Promjeni termin</a>
+</div>
+
+
+ime: <input name="reservation.name" ng:required>
+<br>
+prezime: <input name="reservation.surname" ng:required>
+<br>
+e-mail: <input name="reservation.email" ng:required>
+<br>
+odsjek: <input name="reservation.odsjek" ng:required>
+<br>
+zvanje: <input name="reservation.zvanje">
+<br>
+područke/tema zaninimanja: <input name="reservation.porducje">
+<br>
+<input type=button ng:click="save_submission()" value="Prijavi me" ng:disable="$invalidWidgets.visible()">
+</form>
+
+<input name=debug type=checkbox>
+<pre ng:show="debug">
+reservation={{reservation}}
+submited={{submited}}
+data={{data}}
+</pre>
+
+</div>
+
+
+</body>
+</html>
test -f public/angular/build/angular.js || ( cd public/angular && rake compile )
fi
-./angular-server.pl daemon --reload --listen 'http://*:3001'
+morbo ./angular-server.pl --listen 'http://*:3001'