Slim frontend for API and serialization tests
diff --git a/lib/Korap/Example.pm b/lib/Korap/Example.pm
new file mode 100644
index 0000000..58fbd8b
--- /dev/null
+++ b/lib/Korap/Example.pm
@@ -0,0 +1,12 @@
+package Korap::Example;
+use Mojo::Base 'Mojolicious::Controller';
+
+# This action will render a template
+sub welcome {
+ my $self = shift;
+
+ # Render template "example/welcome.html.ep" with message
+ $self->render(msg => 'Welcome to the Mojolicious real-time web framework!');
+}
+
+1;
diff --git a/lib/Korap/Plugin/KorapSearch.pm b/lib/Korap/Plugin/KorapSearch.pm
new file mode 100644
index 0000000..0245e5d
--- /dev/null
+++ b/lib/Korap/Plugin/KorapSearch.pm
@@ -0,0 +1,136 @@
+package Korap::Plugin::KorapSearch;
+use Mojo::Base 'Mojolicious::Plugin';
+use Mojo::ByteStream 'b';
+
+sub register {
+ my ($plugin, $mojo, $param) = @_;
+ $param ||= {};
+
+ # Load parameter from Config file
+ if (my $config_param = $mojo->config('KorAP')) {
+ $param = { %$config_param, %$param };
+ };
+
+ my $api = $param->{api};
+
+ $mojo->helper(
+ search => sub {
+ my $c = shift;
+
+ # Todo: If there is no callback, return the hits object!
+ my $cb = pop if ref $_[-1] && ref $_[-1] eq 'CODE';
+
+ my %param = @_;
+
+ $c->stash(
+ 'search.count' =>
+ delete($param{count}) //
+ scalar($c->param('count')) //
+ $param->{count}
+ );
+
+ $c->stash('search.startPage' =>
+ (delete($param{startPage}) //
+ scalar $c->param('p') //
+ 1
+ ));
+
+ my $query = $param{query} // scalar $c->param('q');
+
+ return '' unless $query;
+
+ # Get stash information
+ my $count = $c->stash('search.count');
+ my $start_page = $c->stash('search.startPage');
+
+ foreach ($start_page, $count) {
+ $_ = undef if (!$_ || $_ !~ /^\d+$/);
+ };
+
+ my $url = Mojo::URL->new($api);
+ $url->path('resource/search');
+ #if ($c->stash('resource')) {
+ #$url->path($c->stash('resource'));
+ #if ($c->stash('cid')) {
+ #$url->path($c->stash('cid'));
+ #};
+ #};
+
+ my %query = (q => $query);
+ $query{ql} = scalar $c->param('ql') // 'poliqarp';
+ $query{startPage} = $start_page if $start_page;
+ $query{count} = $count if $count;
+
+ $query{lctx} = 'chars';
+ $query{lctxs} = 120;
+ $query{rctx} = 'chars';
+ $query{rctxs} = 120;
+
+ $url->query(\%query);
+
+ $c->stash('search.totalResults' => 0);
+ $c->stash('search.itemsPerPage' => $count);
+
+ my $ua = Mojo::UserAgent->new($url);
+ $c->app->log->debug($url->to_string);
+ my $tx = $ua->get($url);
+
+ if (my $res = $tx->success) {
+ my $json = $res->json;
+
+ my $b_hit = $json->{benchmarkHitCounter};
+ my $b_search = $json->{benchmarkSearchResults};
+
+ if ($b_hit =~ s/\s+(m)?s$//) {
+ $b_hit = sprintf("%.2f", $b_hit) . ($1 ? $1 : '') . 's';
+ };
+ if ($b_search =~ s/\s+(m)?s$//) {
+ $b_search = sprintf("%.2f", $b_search) . ($1 ? $1 : '') . 's';
+ };
+
+ $c->stash('search.bm.hit' => $b_hit);
+ $c->stash('search.bm.result' => $b_search);
+ $c->stash('search.itemsPerPage' => $json->{itemsPerPage});
+ if ($json->{error}) {
+ $c->notify('error' => $json->{error});
+ };
+ $c->stash('search.query' => $json->{request}->{query});
+ $c->stash('search.hits' => $json->{matches});
+ $c->stash('search.totalResults' => $json->{totalResults});
+ }
+ else {
+ my $res = $tx->res;
+ $c->notify('error' => $res->code . ': ' . $res->message);
+ };
+ my $v = $cb->();
+ foreach (qw/hits totalResults bm.hit bm.result itemsPerPage error query/) {
+ delete $c->stash->{'search.' . $_};
+ };
+ return $v;
+ }
+ );
+
+ $mojo->helper(
+ search_hits => sub {
+ my $c = shift;
+ my $cb = pop;
+
+ if (!ref $cb || !(ref $cb eq 'CODE')) {
+ $mojo->log->error("search_hits expects a code block");
+ return '';
+ };
+
+ my $hits = delete $c->stash->{'search.hits'};
+ my $string;
+ foreach (@$hits) {
+ local $_ = $_;
+ $c->stash('search.hit' => $_);
+ $string .= $cb->($_);
+ };
+ delete $c->stash->{'lucy.hit'};
+ return b($string || '');
+ }
+ );
+};
+
+1;
diff --git a/lib/Korap/Plugin/Notifications.pm b/lib/Korap/Plugin/Notifications.pm
new file mode 100644
index 0000000..c07df47
--- /dev/null
+++ b/lib/Korap/Plugin/Notifications.pm
@@ -0,0 +1,136 @@
+package Korap::Plugin::Notifications;
+use Mojo::Base 'Mojolicious::Plugin';
+use Mojo::Util qw/camelize/;
+
+our $TYPE_RE = qr/^[-a-zA-Z_]+$/;
+
+# Todo: Support multiple notification center,
+# so the notifications can be part of
+# json as well as XML
+# Possibly use 'n!.a' for flash as this will be in the cookie!
+
+sub register {
+ my ($plugin, $mojo, $param) = @_;
+
+ $param ||= {};
+
+ # Load parameter from Config file
+ if (my $config_param = $mojo->config('Notifications')) {
+ $param = { %$config_param, %$param };
+ };
+
+ my $debug = $mojo->mode eq 'development' ? 1 : 0;
+
+ my $center = camelize(delete $param->{use} // __PACKAGE__ . '::HTML');
+
+ if (index($center,'::') < 0) {
+ $center = __PACKAGE__ . '::' . $center;
+ };
+
+ my $center_plugin = $mojo->plugins->load_plugin($center);
+ $center_plugin->register($mojo, $param);
+
+ # Add notifications
+ $mojo->helper(
+ notify => sub {
+ my $c = shift;
+ my $type = shift;
+
+ return if $type !~ $TYPE_RE || (!$debug && $type eq 'debug');
+
+ my $array;
+
+ # New notifications
+ if ($array = $c->stash('notify.array')) {
+ push @$array, [$type => @_];
+ }
+
+ # Notifications already set
+ else {
+ $c->stash->{'notify.array'} = [[$type => @_]];
+ };
+ }
+ );
+
+ # Make notifications flash in case of a redirect
+ $mojo->hook(
+ after_dispatch => sub {
+ my ($c) = @_;
+ if ($c->stash('notify.array') && $c->res->is_status_class(300)) {
+ $c->flash('notify.array' => delete $c->stash->{'notify.array'});
+ };
+ }
+ );
+
+ # Embed notification display
+ $mojo->helper(
+ notifications => sub {
+ my $c = shift;
+
+ my @notify_array;
+
+ # Get flash notifications
+ my $flash = $c->flash('notify.array');
+ if ($flash && ref $flash eq 'ARRAY') {
+
+ # Ensure that no harmful types are injected
+ push @notify_array, grep { $_->[0] =~ $TYPE_RE } @$flash;
+
+ $c->flash('notify.array' => undef);
+ };
+
+ # Get stash notifications
+ if ($c->stash('notify.array')) {
+ push @notify_array, @{ delete $c->stash->{'notify.array'} };
+ };
+
+ # Nothing to do
+ return '' unless @notify_array or @_;
+
+ # Forward messages to notification center
+ $center_plugin->notifications($c, \@notify_array, @_);
+ }
+ );
+};
+
+
+1;
+
+
+__END__
+
+=head2 notify
+
+ $c->notify(error => 'Something went wrong');
+ $c->notify(error => { timeout => 4000 } => 'Something went wrong');
+
+=head2 notifications
+
+ %= include_notification_center
+ %= include_notification_center qw/warn error success/
+
+The notification won't be included in case no notifications are
+in the queue and no parameters are passed.
+
+
+
+% if (flash('fine') || flash('alert') || stash('fine') || stash('alert')) {
+%= javascript '/js/humane.min.js'
+%= javascript begin
+ humane.baseCls = 'humane-libnotify';
+% if (flash('fine') || stash('fine')) {
+ humane.log("<%= l(flash('fine') || stash('fine')) %>", {
+ timeout: 3000,
+ clickToClose: true,
+ addnCls: 'humane-libnotify-success'
+ });
+% };
+% if (flash('alert') || stash('alert')) {
+ humane.log("<%= l(flash('alert') || stash('alert')) %>", {
+ timeout: 3000,
+ clickToClose: true,
+ addnCls: 'humane-libnotify-error'
+ });
+% };
+%= end
+% };
diff --git a/lib/Korap/Plugin/Notifications/HTML.pm b/lib/Korap/Plugin/Notifications/HTML.pm
new file mode 100644
index 0000000..24a0623
--- /dev/null
+++ b/lib/Korap/Plugin/Notifications/HTML.pm
@@ -0,0 +1,33 @@
+package Korap::Plugin::Notifications::HTML;
+use Mojo::Base 'Mojolicious::Plugin';
+use Mojo::Collection 'c';
+use Mojo::ByteStream 'b';
+use Mojo::Util qw/xml_escape/;
+
+# Nothing to register
+sub register {};
+
+
+# Notification method
+sub notifications {
+ my ($self, $c, $notify_array) = @_;
+
+ my $html = '';
+ foreach my $note (@$notify_array) {
+ my $type = shift @$note;
+ $html .= qq{<div class="notify-$type">};
+ $html .= c(@$note)->grep(sub { !ref $_ })
+ ->map(sub { return xml_escape($_) })
+ ->join('<br />')
+ ->to_string;
+ $html .= "</div>\n";
+ };
+
+ return b $html;
+};
+
+
+1;
+
+
+__END__
diff --git a/lib/Korap/Plugin/Notifications/Humane.pm b/lib/Korap/Plugin/Notifications/Humane.pm
new file mode 100644
index 0000000..44810c3
--- /dev/null
+++ b/lib/Korap/Plugin/Notifications/Humane.pm
@@ -0,0 +1,76 @@
+package Korap::Plugin::Notifications::Humane;
+use Mojo::Base 'Mojolicious::Plugin';
+use Mojo::ByteStream 'b';
+use Mojo::JSON;
+use File::Spec;
+use File::Basename;
+
+has json => sub {
+ state $json = Mojo::JSON->new
+};
+
+has [qw/base_class base_timeout/];
+
+# Register plugin
+sub register {
+ my ($plugin, $mojo, $param) = @_;
+
+ # Set config
+ $plugin->base_class( $param->{base_class} // 'libnotify' );
+ $plugin->base_timeout( $param->{base_timeout} // 3000 );
+
+ # Add static path to JavaScript
+ push @{$mojo->static->paths},
+ File::Spec->catdir( File::Basename::dirname(__FILE__), 'Humane' );
+};
+
+
+# Notification method
+sub notifications {
+ my ($self, $c, $notify_array, @classes) = @_;
+
+ my $base_class = $self->base_class;
+
+ my %rule;
+ while ($classes[0] && index($classes[0], '-') == 0) {
+ $rule{shift @classes} = 1;
+ };
+
+ return unless @$notify_array || @classes;
+
+ my $js = '';
+ unless ($rule{-no_include}) {
+ $js .= $c->javascript('/humane.min.js');
+ };
+
+ unless ($rule{-no_css}) {
+ $js .= $c->stylesheet("/$base_class.css");;
+ };
+
+ # Start JavaScript snippet
+ $js .= qq{<script>\n} .
+ qq!var notify=humane.create({baseCls:'humane-$base_class',timeout:! .
+ $self->base_timeout . ",clickToClose:true});\n";
+
+ my ($log, %notify) = ('');
+
+ # Add notifications
+ foreach (@$notify_array) {
+ $notify{$_->[0]} = 1;
+ $log .= '.' . $_->[0] . '(' . $self->json->encode($_->[1]) . ')';
+ };
+ $log = "notify$log;\n" if $log;
+
+ # Ceate notification classes
+ foreach (sort(keys %notify), @classes) {
+ $js .= "notify.$_=notify.spawn({addnCls:'humane-$base_class-$_'});\n";
+ };
+
+ return b($js . $log . '</script>');
+};
+
+
+1;
+
+
+__END__
diff --git a/lib/Korap/Plugin/Notifications/Humane/bigbox.css b/lib/Korap/Plugin/Notifications/Humane/bigbox.css
new file mode 100644
index 0000000..8d369bb
--- /dev/null
+++ b/lib/Korap/Plugin/Notifications/Humane/bigbox.css
@@ -0,0 +1,123 @@
+html,
+body {
+ min-height: 100%;
+}
+.humane,
+.humane-bigbox {
+ position: fixed;
+ -moz-transition: all 0.3s ease-out;
+ -webkit-transition: all 0.3s ease-out;
+ -ms-transition: all 0.3s ease-out;
+ -o-transition: all 0.3s ease-out;
+ transition: all 0.3s ease-out;
+ z-index: 100000;
+ filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100);
+}
+.humane,
+.humane-bigbox {
+ font-family: Ubuntu, Verdana, sans-serif;
+ line-height: 40px;
+ font-size: 35px;
+ top: 25%;
+ left: 25%;
+ opacity: 0;
+ width: 50%;
+ min-height: 40px;
+ padding: 30px;
+ text-align: center;
+ background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAADICAYAAAAp8ov1AAAABmJLR0QA/wD/AP+gvaeTAAAAc0lEQVQokb2RQQ6EMAwDx/7/n80BtIEC3RYhLlXrVLGTAYiBWBIGtkPSP01SfreTVoV5re9Rcee1scwDk9NurbR62sZJcpzy9O+2X5KsXabyPaQFYNuvkqkRviDTp9Vs8opC0TpkHvJtVjeReW/5kEyX1gKeLEKE9peeWAAAAABJRU5ErkJggg==');
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0, #000), color-stop(1, rgba(0,0,0,0.9))) no-repeat;
+ background: -moz-linear-gradient(top, #000 0%, rgba(0,0,0,0.9) 100%) no-repeat;
+ background: -webkit-linear-gradient(top, #000 0%, rgba(0,0,0,0.9) 100%) no-repeat;
+ background: -ms-linear-gradient(top, #000 0%, rgba(0,0,0,0.9) 100%) no-repeat;
+ background: -o-linear-gradient(top, #000 0%, rgba(0,0,0,0.9) 100%) no-repeat;
+ background: linear-gradient(top, #000 0%, rgba(0,0,0,0.9) 100%) no-repeat;
+ *background-color: #000;
+ color: #fff;
+ -webkit-border-radius: 15px;
+ border-radius: 15px;
+ text-shadow: 0 -1px 1px #ddd;
+ -webkit-box-shadow: 0 15px 15px -15px #000;
+ box-shadow: 0 15px 15px -15px #000;
+ -moz-transform: scale(0.1);
+ -webkit-transform: scale(0.1);
+ -ms-transform: scale(0.1);
+ -o-transform: scale(0.1);
+ transform: scale(0.1);
+}
+.humane p,
+.humane-bigbox p,
+.humane ul,
+.humane-bigbox ul {
+ margin: 0;
+ padding: 0;
+}
+.humane ul,
+.humane-bigbox ul {
+ list-style: none;
+}
+.humane.humane-bigbox-info,
+.humane-bigbox.humane-bigbox-info {
+ background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAADICAYAAAAp8ov1AAAABmJLR0QA/wD/AP+gvaeTAAAAQElEQVQokWNgYEj5z8TAwPCfiYGBgQGVIEKMTG2DTYwRVez/IHIaNcUGyBnYgpORel6gpvFEJhBqpxIaG8/AAADsKDq/HhYQ2AAAAABJRU5ErkJggg==');
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0, #000064), color-stop(1, rgba(0,0,100,0.9))) no-repeat;
+ background: -moz-linear-gradient(top, #000064 0%, rgba(0,0,100,0.9) 100%) no-repeat;
+ background: -webkit-linear-gradient(top, #000064 0%, rgba(0,0,100,0.9) 100%) no-repeat;
+ background: -ms-linear-gradient(top, #000064 0%, rgba(0,0,100,0.9) 100%) no-repeat;
+ background: -o-linear-gradient(top, #000064 0%, rgba(0,0,100,0.9) 100%) no-repeat;
+ background: linear-gradient(top, #000064 0%, rgba(0,0,100,0.9) 100%) no-repeat;
+ *background-color: #030;
+}
+.humane.humane-bigbox-success,
+.humane-bigbox.humane-bigbox-success {
+ background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAADICAYAAAAp8ov1AAAABmJLR0QA/wD/AP+gvaeTAAAAPklEQVQokWNgSGH4z8TAACEYUAkixMjUNsjEGFHF/g8ip1FVbGCcgS04GannBaoaT1wCwWkvmXbQ2HgGBgYA8Yw6v+m4Kh8AAAAASUVORK5CYII=');
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0, #006400), color-stop(1, rgba(0,100,0,0.9))) no-repeat;
+ background: -moz-linear-gradient(top, #006400 0%, rgba(0,100,0,0.9) 100%) no-repeat;
+ background: -webkit-linear-gradient(top, #006400 0%, rgba(0,100,0,0.9) 100%) no-repeat;
+ background: -ms-linear-gradient(top, #006400 0%, rgba(0,100,0,0.9) 100%) no-repeat;
+ background: -o-linear-gradient(top, #006400 0%, rgba(0,100,0,0.9) 100%) no-repeat;
+ background: linear-gradient(top, #006400 0%, rgba(0,100,0,0.9) 100%) no-repeat;
+ *background-color: #030;
+}
+.humane.humane-bigbox-error,
+.humane-bigbox.humane-bigbox-error {
+ background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAADICAYAAAAp8ov1AAAABmJLR0QA/wD/AP+gvaeTAAAAPklEQVQokWNIYWD4z8QAJRhQCSLEyNQ2uMQYUcX+DyKnUVdsQJyBLTgZqecF6hpPVALBaS+ZdtDYeAYGBgYA9vA6v4OR3MkAAAAASUVORK5CYII=');
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0, #640000), color-stop(1, rgba(100,0,0,0.9))) no-repeat;
+ background: -moz-linear-gradient(top, #640000 0%, rgba(100,0,0,0.9) 100%) no-repeat;
+ background: -webkit-linear-gradient(top, #640000 0%, rgba(100,0,0,0.9) 100%) no-repeat;
+ background: -ms-linear-gradient(top, #640000 0%, rgba(100,0,0,0.9) 100%) no-repeat;
+ background: -o-linear-gradient(top, #640000 0%, rgba(100,0,0,0.9) 100%) no-repeat;
+ background: linear-gradient(top, #640000 0%, rgba(100,0,0,0.9) 100%) no-repeat;
+ *background-color: #300;
+}
+.humane.humane-animate,
+.humane-bigbox.humane-bigbox-animate {
+ opacity: 1;
+ -moz-transform: scale(1);
+ -webkit-transform: scale(1);
+ -ms-transform: scale(1);
+ -o-transform: scale(1);
+ transform: scale(1);
+}
+.humane.humane-animate:hover,
+.humane-bigbox.humane-bigbox-animate:hover {
+ opacity: 0.6;
+ -moz-transform: scale(0.8);
+ -webkit-transform: scale(0.8);
+ -ms-transform: scale(0.8);
+ -o-transform: scale(0.8);
+ transform: scale(0.8);
+}
+.humane.humane-js-animate,
+.humane-bigbox.humane-bigbox-js-animate {
+ opacity: 1;
+ -moz-transform: scale(1);
+ -webkit-transform: scale(1);
+ -ms-transform: scale(1);
+ -o-transform: scale(1);
+ transform: scale(1);
+}
+.humane.humane-js-animate:hover,
+.humane-bigbox.humane-bigbox-js-animate:hover {
+ opacity: 0.6;
+ filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=60);
+}
diff --git a/lib/Korap/Plugin/Notifications/Humane/boldlight.css b/lib/Korap/Plugin/Notifications/Humane/boldlight.css
new file mode 100644
index 0000000..d338ed2
--- /dev/null
+++ b/lib/Korap/Plugin/Notifications/Humane/boldlight.css
@@ -0,0 +1,122 @@
+html,
+body {
+ min-height: 100%;
+}
+.humane,
+.humane-boldlight {
+ position: fixed;
+ -moz-transition: all 0.3s ease-out;
+ -webkit-transition: all 0.3s ease-out;
+ -ms-transition: all 0.3s ease-out;
+ -o-transition: all 0.3s ease-out;
+ transition: all 0.3s ease-out;
+ z-index: 100000;
+ filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100);
+}
+.humane,
+.humane-boldlight {
+ font-family: Ubuntu, Verdana, sans-serif;
+ font-size: 25px;
+ letter-spacing: -1px;
+ top: 25%;
+ left: 25%;
+ opacity: 0;
+ width: 50%;
+ color: #000;
+ padding: 10px;
+ text-align: center;
+ background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAACWCAYAAAAfduJyAAAABmJLR0QA/wD/AP+gvaeTAAAAPElEQVQokWP4////Gab///8zQAgGBgYo8e/fP2QxSpSgydJNCYJLRSVoPqeOkgEIYop9TrGbSfcWpW4GAFeF/7lb/oWBAAAAAElFTkSuQmCC');
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0, rgba(255,255,255,0.8)), color-stop(1, rgba(150,150,150,0.8))) no-repeat;
+ background: -moz-linear-gradient(top, rgba(255,255,255,0.8) 0%, rgba(150,150,150,0.8) 100%) no-repeat;
+ background: -webkit-linear-gradient(top, rgba(255,255,255,0.8) 0%, rgba(150,150,150,0.8) 100%) no-repeat;
+ background: -ms-linear-gradient(top, rgba(255,255,255,0.8) 0%, rgba(150,150,150,0.8) 100%) no-repeat;
+ background: -o-linear-gradient(top, rgba(255,255,255,0.8) 0%, rgba(150,150,150,0.8) 100%) no-repeat;
+ background: linear-gradient(top, rgba(255,255,255,0.8) 0%, rgba(150,150,150,0.8) 100%) no-repeat;
+ *background-color: #fff;
+ -webkit-border-radius: 15px;
+ border-radius: 15px;
+ text-shadow: 0 -1px 1px rgba(221,221,221,0.4);
+ -webkit-box-shadow: 0 4px 4px -4px #eee;
+ box-shadow: 0 4px 4px -4px #eee;
+ -moz-transform: scale(1.1);
+ -webkit-transform: scale(1.1);
+ -ms-transform: scale(1.1);
+ -o-transform: scale(1.1);
+ transform: scale(1.1);
+}
+.humane p,
+.humane-boldlight p,
+.humane ul,
+.humane-boldlight ul {
+ margin: 0;
+ padding: 0;
+}
+.humane ul,
+.humane-boldlight ul {
+ list-style: none;
+}
+.humane.humane-boldlight-info,
+.humane-boldlight.humane-boldlight-info {
+ background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAADICAYAAAAp8ov1AAAABmJLR0QA/wD/AP+gvaeTAAAAR0lEQVQokWNISfn/n4mBgeE/EwMDAwMqQYQYmdoGlxgjI4rY//+Dx2nUFRsQZ2ALTrQQp8QL1DWeqASC014y7aCx8QwMDAwA1aZBIulmpvwAAAAASUVORK5CYII=');
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0, #6464ff), color-stop(1, rgba(100,100,255,0.8))) no-repeat;
+ background: -moz-linear-gradient(top, #6464ff 0%, rgba(100,100,255,0.8) 100%) no-repeat;
+ background: -webkit-linear-gradient(top, #6464ff 0%, rgba(100,100,255,0.8) 100%) no-repeat;
+ background: -ms-linear-gradient(top, #6464ff 0%, rgba(100,100,255,0.8) 100%) no-repeat;
+ background: -o-linear-gradient(top, #6464ff 0%, rgba(100,100,255,0.8) 100%) no-repeat;
+ background: linear-gradient(top, #6464ff 0%, rgba(100,100,255,0.8) 100%) no-repeat;
+ *background-color: #6464ff;
+}
+.humane.humane-boldlight-success,
+.humane-boldlight.humane-boldlight-success {
+ background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAADICAYAAAAp8ov1AAAABmJLR0QA/wD/AP+gvaeTAAAAGklEQVQokWNI+Z9yhomBgYFhlBglRonhSgAAFX0EItSd0k8AAAAASUVORK5CYII=');
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0, #64ff64), color-stop(1, rgba(100,255,100,0.8))) no-repeat;
+ background: -moz-linear-gradient(top, #64ff64 0%, rgba(100,255,100,0.8) 100%) no-repeat;
+ background: -webkit-linear-gradient(top, #64ff64 0%, rgba(100,255,100,0.8) 100%) no-repeat;
+ background: -ms-linear-gradient(top, #64ff64 0%, rgba(100,255,100,0.8) 100%) no-repeat;
+ background: -o-linear-gradient(top, #64ff64 0%, rgba(100,255,100,0.8) 100%) no-repeat;
+ background: linear-gradient(top, #64ff64 0%, rgba(100,255,100,0.8) 100%) no-repeat;
+ *background-color: #64ff64;
+}
+.humane.humane-boldlight-error,
+.humane-boldlight.humane-boldlight-error {
+ background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAADICAYAAAAp8ov1AAAABmJLR0QA/wD/AP+gvaeTAAAAGklEQVQokWP4n5JyhomBgYFhlBglRonhSgAAFhgEIhjGqQkAAAAASUVORK5CYII=');
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0, #ff6464), color-stop(1, rgba(255,100,100,0.8))) no-repeat;
+ background: -moz-linear-gradient(top, #ff6464 0%, rgba(255,100,100,0.8) 100%) no-repeat;
+ background: -webkit-linear-gradient(top, #ff6464 0%, rgba(255,100,100,0.8) 100%) no-repeat;
+ background: -ms-linear-gradient(top, #ff6464 0%, rgba(255,100,100,0.8) 100%) no-repeat;
+ background: -o-linear-gradient(top, #ff6464 0%, rgba(255,100,100,0.8) 100%) no-repeat;
+ background: linear-gradient(top, #ff6464 0%, rgba(255,100,100,0.8) 100%) no-repeat;
+ *background-color: #ff6464;
+}
+.humane.humane-animate,
+.humane-boldlight.humane-boldlight-animate {
+ opacity: 1;
+ -moz-transform: scale(1);
+ -webkit-transform: scale(1);
+ -ms-transform: scale(1);
+ -o-transform: scale(1);
+ transform: scale(1);
+}
+.humane.humane-animate:hover,
+.humane-boldlight.humane-boldlight-animate:hover {
+ opacity: 0.4;
+ -moz-transform: scale(1.8);
+ -webkit-transform: scale(1.8);
+ -ms-transform: scale(1.8);
+ -o-transform: scale(1.8);
+ transform: scale(1.8);
+}
+.humane.humane-animate,
+.humane-boldlight.humane-boldlight-js-animate {
+ opacity: 1;
+ -moz-transform: scale(1);
+ -webkit-transform: scale(1);
+ -ms-transform: scale(1);
+ -o-transform: scale(1);
+ transform: scale(1);
+}
+.humane.humane-animate:hover,
+.humane-boldlight.humane-boldlight-js-animate:hover {
+ opacity: 0.4;
+ filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=40);
+}
diff --git a/lib/Korap/Plugin/Notifications/Humane/flatty.css b/lib/Korap/Plugin/Notifications/Humane/flatty.css
new file mode 100644
index 0000000..74d94f8
--- /dev/null
+++ b/lib/Korap/Plugin/Notifications/Humane/flatty.css
@@ -0,0 +1,94 @@
+html,
+body {
+ min-height: 100%;
+}
+.humane,
+.humane-flatty {
+ position: fixed;
+ -moz-transition: all 0.4s ease-in-out;
+ -webkit-transition: all 0.4s ease-in-out;
+ -ms-transition: all 0.4s ease-in-out;
+ -o-transition: all 0.4s ease-in-out;
+ transition: all 0.4s ease-in-out;
+ z-index: 100000;
+ filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100);
+}
+.humane,
+.humane-flatty {
+ font-family: Helvetica Neue, Helvetica, san-serif;
+ font-size: 16px;
+ top: 0;
+ left: 30%;
+ opacity: 0;
+ width: 40%;
+ color: #444;
+ padding: 10px;
+ text-align: center;
+ background-color: #fff;
+ -webkit-border-bottom-right-radius: 3px;
+ -webkit-border-bottom-left-radius: 3px;
+ -moz-border-radius-bottomright: 3px;
+ -moz-border-radius-bottomleft: 3px;
+ border-bottom-right-radius: 3px;
+ border-bottom-left-radius: 3px;
+ -webkit-box-shadow: 0 1px 2px rgba(0,0,0,0.5);
+ box-shadow: 0 1px 2px rgba(0,0,0,0.5);
+ -moz-transform: translateY(-100px);
+ -webkit-transform: translateY(-100px);
+ -ms-transform: translateY(-100px);
+ -o-transform: translateY(-100px);
+ transform: translateY(-100px);
+}
+.humane p,
+.humane-flatty p,
+.humane ul,
+.humane-flatty ul {
+ margin: 0;
+ padding: 0;
+}
+.humane ul,
+.humane-flatty ul {
+ list-style: none;
+}
+.humane.humane-flatty-info,
+.humane-flatty.humane-flatty-info {
+ background-color: #3498db;
+ color: #FFF;
+}
+.humane.humane-flatty-success,
+.humane-flatty.humane-flatty-success {
+ background-color: #18bc9c;
+ color: #FFF;
+}
+.humane.humane-flatty-error,
+.humane-flatty.humane-flatty-error {
+ background-color: #e74c3c;
+ color: #FFF;
+}
+.humane-animate,
+.humane-flatty.humane-flatty-animate {
+ opacity: 1;
+ -moz-transform: translateY(0);
+ -webkit-transform: translateY(0);
+ -ms-transform: translateY(0);
+ -o-transform: translateY(0);
+ transform: translateY(0);
+}
+.humane-animate:hover,
+.humane-flatty.humane-flatty-animate:hover {
+ opacity: 0.7;
+}
+.humane-js-animate,
+.humane-flatty.humane-flatty-js-animate {
+ opacity: 1;
+ -moz-transform: translateY(0);
+ -webkit-transform: translateY(0);
+ -ms-transform: translateY(0);
+ -o-transform: translateY(0);
+ transform: translateY(0);
+}
+.humane-js-animate:hover,
+.humane-flatty.humane-flatty-js-animate:hover {
+ opacity: 0.7;
+ filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=70);
+}
diff --git a/lib/Korap/Plugin/Notifications/Humane/humane.min.js b/lib/Korap/Plugin/Notifications/Humane/humane.min.js
new file mode 100644
index 0000000..59a7453
--- /dev/null
+++ b/lib/Korap/Plugin/Notifications/Humane/humane.min.js
@@ -0,0 +1 @@
+!function(t,e,i){"undefined"!=typeof module?module.exports=i(t,e):"function"==typeof define&&"object"==typeof define.amd?define(i):e[t]=i(t,e)}("humane",this,function(){var t=window,e=document,i={on:function(e,i,n){"addEventListener"in t?e.addEventListener(i,n,!1):e.attachEvent("on"+i,n)},off:function(e,i,n){"removeEventListener"in t?e.removeEventListener(i,n,!1):e.detachEvent("on"+i,n)},bind:function(t,e){return function(){t.apply(e,arguments)}},isArray:Array.isArray||function(t){return"[object Array]"===Object.prototype.toString.call(t)},config:function(t,e){return null!=t?t:e},transSupport:!1,useFilter:/msie [678]/i.test(navigator.userAgent),_checkTransition:function(){var t=e.createElement("div"),i={webkit:"webkit",Moz:"",O:"o",ms:"MS"};for(var n in i)n+"Transition"in t.style&&(this.vendorPrefix=i[n],this.transSupport=!0)}};i._checkTransition();var n=function(e){e||(e={}),this.queue=[],this.baseCls=e.baseCls||"humane",this.addnCls=e.addnCls||"",this.timeout="timeout"in e?e.timeout:2500,this.waitForMove=e.waitForMove||!1,this.clickToClose=e.clickToClose||!1,this.timeoutAfterMove=e.timeoutAfterMove||!1,this.container=e.container;try{this._setupEl()}catch(n){i.on(t,"load",i.bind(this._setupEl,this))}};return n.prototype={constructor:n,_setupEl:function(){var t=e.createElement("div");if(t.style.display="none",!this.container){if(!e.body)throw"document.body is null";this.container=e.body}this.container.appendChild(t),this.el=t,this.removeEvent=i.bind(function(){this.timeoutAfterMove?setTimeout(i.bind(this.remove,this),this.timeout):this.remove()},this),this.transEvent=i.bind(this._afterAnimation,this),this._run()},_afterTimeout:function(){i.config(this.currentMsg.waitForMove,this.waitForMove)?this.removeEventsSet||(i.on(e.body,"mousemove",this.removeEvent),i.on(e.body,"click",this.removeEvent),i.on(e.body,"keypress",this.removeEvent),i.on(e.body,"touchstart",this.removeEvent),this.removeEventsSet=!0):this.remove()},_run:function(){if(!this._animating&&this.queue.length&&this.el){this._animating=!0,this.currentTimer&&(clearTimeout(this.currentTimer),this.currentTimer=null);var t=this.queue.shift(),e=i.config(t.clickToClose,this.clickToClose);e&&(i.on(this.el,"click",this.removeEvent),i.on(this.el,"touchstart",this.removeEvent));var n=i.config(t.timeout,this.timeout);n>0&&(this.currentTimer=setTimeout(i.bind(this._afterTimeout,this),n)),i.isArray(t.html)&&(t.html="<ul><li>"+t.html.join("<li>")+"</ul>"),this.el.innerHTML=t.html,this.currentMsg=t,this.el.className=this.baseCls,i.transSupport?(this.el.style.display="block",setTimeout(i.bind(this._showMsg,this),50)):this._showMsg()}},_setOpacity:function(t){if(i.useFilter)try{this.el.filters.item("DXImageTransform.Microsoft.Alpha").Opacity=100*t}catch(e){}else this.el.style.opacity=String(t)},_showMsg:function(){var t=i.config(this.currentMsg.addnCls,this.addnCls);if(i.transSupport)this.el.className=this.baseCls+" "+t+" "+this.baseCls+"-animate";else{var e=0;this.el.className=this.baseCls+" "+t+" "+this.baseCls+"-js-animate",this._setOpacity(0),this.el.style.display="block";var n=this,s=setInterval(function(){1>e?(e+=.1,e>1&&(e=1),n._setOpacity(e)):clearInterval(s)},30)}},_hideMsg:function(){var t=i.config(this.currentMsg.addnCls,this.addnCls);if(i.transSupport)this.el.className=this.baseCls+" "+t,i.on(this.el,i.vendorPrefix?i.vendorPrefix+"TransitionEnd":"transitionend",this.transEvent);else var e=1,n=this,s=setInterval(function(){e>0?(e-=.1,0>e&&(e=0),n._setOpacity(e)):(n.el.className=n.baseCls+" "+t,clearInterval(s),n._afterAnimation())},30)},_afterAnimation:function(){i.transSupport&&i.off(this.el,i.vendorPrefix?i.vendorPrefix+"TransitionEnd":"transitionend",this.transEvent),this.currentMsg.cb&&this.currentMsg.cb(),this.el.style.display="none",this._animating=!1,this._run()},remove:function(t){var n="function"==typeof t?t:null;i.off(e.body,"mousemove",this.removeEvent),i.off(e.body,"click",this.removeEvent),i.off(e.body,"keypress",this.removeEvent),i.off(e.body,"touchstart",this.removeEvent),i.off(this.el,"click",this.removeEvent),i.off(this.el,"touchstart",this.removeEvent),this.removeEventsSet=!1,n&&this.currentMsg&&(this.currentMsg.cb=n),this._animating?this._hideMsg():n&&n()},log:function(t,e,i,n){var s={};if(n)for(var o in n)s[o]=n[o];if("function"==typeof e)i=e;else if(e)for(var o in e)s[o]=e[o];return s.html=t,i&&(s.cb=i),this.queue.push(s),this._run(),this},spawn:function(t){var e=this;return function(i,n,s){return e.log.call(e,i,n,s,t),e}},create:function(t){return new n(t)}},new n});
\ No newline at end of file
diff --git a/lib/Korap/Plugin/Notifications/Humane/jackedup.css b/lib/Korap/Plugin/Notifications/Humane/jackedup.css
new file mode 100644
index 0000000..cbc6aa9
--- /dev/null
+++ b/lib/Korap/Plugin/Notifications/Humane/jackedup.css
@@ -0,0 +1,123 @@
+html,
+body {
+ min-height: 100%;
+}
+.humane,
+.humane-jackedup {
+ position: fixed;
+ -moz-transition: all 0.6s ease-in-out;
+ -webkit-transition: all 0.6s ease-in-out;
+ -ms-transition: all 0.6s ease-in-out;
+ -o-transition: all 0.6s ease-in-out;
+ transition: all 0.6s ease-in-out;
+ z-index: 100000;
+ filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100);
+}
+.humane,
+.humane-jackedup {
+ font-family: Helvetica Neue, Helvetica, san-serif;
+ font-size: 18px;
+ letter-spacing: -1px;
+ top: 20px;
+ left: 30%;
+ opacity: 0;
+ width: 40%;
+ color: #333;
+ padding: 10px;
+ text-align: center;
+ background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAACWCAYAAAAfduJyAAAABmJLR0QA/wD/AP+gvaeTAAAAIklEQVQokWNgYGCQZGJgYGDARTDSQnboGDqsnDt0DKWNLAAkiQFdC+vZNQAAAABJRU5ErkJggg==');
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0, rgba(0,0,0,0.1)), color-stop(1, rgba(0,0,0,0.2))) no-repeat;
+ background: -moz-linear-gradient(top, rgba(0,0,0,0.1) 0%, rgba(0,0,0,0.2) 100%) no-repeat;
+ background: -webkit-linear-gradient(top, rgba(0,0,0,0.1) 0%, rgba(0,0,0,0.2) 100%) no-repeat;
+ background: -ms-linear-gradient(top, rgba(0,0,0,0.1) 0%, rgba(0,0,0,0.2) 100%) no-repeat;
+ background: -o-linear-gradient(top, rgba(0,0,0,0.1) 0%, rgba(0,0,0,0.2) 100%) no-repeat;
+ background: linear-gradient(top, rgba(0,0,0,0.1) 0%, rgba(0,0,0,0.2) 100%) no-repeat;
+ background-color: #fff;
+ -webkit-border-radius: 3px;
+ border-radius: 3px;
+ text-shadow: 0 1px 1px rgba(255,255,255,0.8);
+ -webkit-box-shadow: 0 1px 2px rgba(0,0,0,0.5);
+ box-shadow: 0 1px 2px rgba(0,0,0,0.5);
+ -moz-transform: translateY(-100px);
+ -webkit-transform: translateY(-100px);
+ -ms-transform: translateY(-100px);
+ -o-transform: translateY(-100px);
+ transform: translateY(-100px);
+}
+.humane p,
+.humane-jackedup p,
+.humane ul,
+.humane-jackedup ul {
+ margin: 0;
+ padding: 0;
+}
+.humane ul,
+.humane-jackedup ul {
+ list-style: none;
+}
+.humane.humane-jackedup-info,
+.humane-jackedup.humane-jackedup-info {
+ background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAADICAYAAAAp8ov1AAAABmJLR0QA/wD/AP+gvaeTAAAAR0lEQVQokWNISfn/n4mBgeE/EwMDAwMqQYQYmdoGlxgjI4rY//+Dx2nUFRsQZ2ALTrQQp8QL1DWeqASC014y7aCx8QwMDAwA1aZBIulmpvwAAAAASUVORK5CYII=');
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0, rgba(0,0,0,0.7)), color-stop(1, rgba(0,0,0,0.85))) no-repeat;
+ background: -moz-linear-gradient(top, rgba(0,0,0,0.7) 0%, rgba(0,0,0,0.85) 100%) no-repeat;
+ background: -webkit-linear-gradient(top, rgba(0,0,0,0.7) 0%, rgba(0,0,0,0.85) 100%) no-repeat;
+ background: -ms-linear-gradient(top, rgba(0,0,0,0.7) 0%, rgba(0,0,0,0.85) 100%) no-repeat;
+ background: -o-linear-gradient(top, rgba(0,0,0,0.7) 0%, rgba(0,0,0,0.85) 100%) no-repeat;
+ background: linear-gradient(top, rgba(0,0,0,0.7) 0%, rgba(0,0,0,0.85) 100%) no-repeat;
+ background-color: #fff;
+ color: #fff;
+ text-shadow: 0 -1px 1px rgba(0,0,0,0.35);
+}
+.humane.humane-jackedup-success,
+.humane-jackedup.humane-jackedup-success {
+ background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAADICAYAAAAp8ov1AAAABmJLR0QA/wD/AP+gvaeTAAAASElEQVQokc2SMQ4AIAgDD9/K/79QVzWaENTownAJbWnA5SqACkA/Aiy59hczrGVC30Q7y57EmNU5NL5zwln50IMsfZMel+UBKtFBQSLWM9wLAAAAAElFTkSuQmCC');
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0, #62c462), color-stop(1, #57a957)) no-repeat;
+ background: -moz-linear-gradient(top, #62c462 0%, #57a957 100%) no-repeat;
+ background: -webkit-linear-gradient(top, #62c462 0%, #57a957 100%) no-repeat;
+ background: -ms-linear-gradient(top, #62c462 0%, #57a957 100%) no-repeat;
+ background: -o-linear-gradient(top, #62c462 0%, #57a957 100%) no-repeat;
+ background: linear-gradient(top, #62c462 0%, #57a957 100%) no-repeat;
+ background-color: #64ff64;
+ color: #fff;
+ text-shadow: 0 -1px 1px rgba(0,0,0,0.35);
+}
+.humane.humane-jackedup-error,
+.humane-jackedup.humane-jackedup-error {
+ background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAADICAIAAACmkByiAAAABmJLR0QA/wD/AP+gvaeTAAAAf0lEQVQokY2TOQ7AIAwER/5mivy/yRc2RQDhA0jhghFYO5bhuS+TZMAoIUMEhhH4loGhfu71cenM3DutWMsaeGKjv3zO5N17KLPJ0+fQD8cpv5uVLPo4vnX0PpXj0nuaaeVzdmw+yXG1O96n2p3kozB757Ni1Z5UPsU9SP8AeAG1kHXE+7RlPAAAAABJRU5ErkJggg==');
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0, #ee5f5b), color-stop(1, #c43c35)) no-repeat;
+ background: -moz-linear-gradient(top, #ee5f5b 0%, #c43c35 100%) no-repeat;
+ background: -webkit-linear-gradient(top, #ee5f5b 0%, #c43c35 100%) no-repeat;
+ background: -ms-linear-gradient(top, #ee5f5b 0%, #c43c35 100%) no-repeat;
+ background: -o-linear-gradient(top, #ee5f5b 0%, #c43c35 100%) no-repeat;
+ background: linear-gradient(top, #ee5f5b 0%, #c43c35 100%) no-repeat;
+ background-color: #ee5f5b;
+ color: #fff;
+ text-shadow: 0 -1px 1px rgba(0,0,0,0.35);
+}
+.humane-animate,
+.humane-jackedup.humane-jackedup-animate {
+ opacity: 1;
+ -moz-transform: translateY(0);
+ -webkit-transform: translateY(0);
+ -ms-transform: translateY(0);
+ -o-transform: translateY(0);
+ transform: translateY(0);
+}
+.humane-animate:hover,
+.humane-jackedup.humane-jackedup-animate:hover {
+ opacity: 0.7;
+}
+.humane-js-animate,
+.humane-jackedup.humane-jackedup-js-animate {
+ opacity: 1;
+ -moz-transform: translateY(0);
+ -webkit-transform: translateY(0);
+ -ms-transform: translateY(0);
+ -o-transform: translateY(0);
+ transform: translateY(0);
+}
+.humane-js-animate:hover,
+.humane-jackedup.humane-jackedup-js-animate:hover {
+ opacity: 0.7;
+ filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=70);
+}
diff --git a/lib/Korap/Plugin/Notifications/Humane/libnotify.css b/lib/Korap/Plugin/Notifications/Humane/libnotify.css
new file mode 100644
index 0000000..7e70c1c
--- /dev/null
+++ b/lib/Korap/Plugin/Notifications/Humane/libnotify.css
@@ -0,0 +1,115 @@
+html,
+body {
+ min-height: 100%;
+}
+.humane,
+.humane-libnotify {
+ position: fixed;
+ -moz-transition: all 0.3s ease-out;
+ -webkit-transition: all 0.3s ease-out;
+ -ms-transition: all 0.3s ease-out;
+ -o-transition: all 0.3s ease-out;
+ transition: all 0.3s ease-out;
+ z-index: 100000;
+ filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100);
+}
+.humane,
+.humane-libnotify {
+ font-family: Ubuntu, Arial, sans-serif;
+ text-align: center;
+ font-size: 15px;
+ top: 10px;
+ right: 10px;
+ opacity: 0;
+ width: 150px;
+ color: #fff;
+ padding: 10px;
+ background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAABQCAYAAADYxx/bAAAABmJLR0QA/wD/AP+gvaeTAAAANElEQVQYlWNgYGB4ysTAwMDAxMjICCUQXDQWAwMDAxMTExMedcRyB6d5CAMQ5hGrjSrmAQBQdgIXlosSTwAAAABJRU5ErkJggg==');
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0, rgba(0,0,0,0.9)), color-stop(1, rgba(50,50,50,0.9))) no-repeat;
+ background: -moz-linear-gradient(top, rgba(0,0,0,0.9) 0%, rgba(50,50,50,0.9) 100%) no-repeat;
+ background: -webkit-linear-gradient(top, rgba(0,0,0,0.9) 0%, rgba(50,50,50,0.9) 100%) no-repeat;
+ background: -ms-linear-gradient(top, rgba(0,0,0,0.9) 0%, rgba(50,50,50,0.9) 100%) no-repeat;
+ background: -o-linear-gradient(top, rgba(0,0,0,0.9) 0%, rgba(50,50,50,0.9) 100%) no-repeat;
+ background: linear-gradient(top, rgba(0,0,0,0.9) 0%, rgba(50,50,50,0.9) 100%) no-repeat;
+ *background-color: #000;
+ -webkit-border-radius: 5px;
+ border-radius: 5px;
+ -webkit-box-shadow: 0 4px 4px -4px #000;
+ box-shadow: 0 4px 4px -4px #000;
+ -moz-transform: translateY(-40px);
+ -webkit-transform: translateY(-40px);
+ -ms-transform: translateY(-40px);
+ -o-transform: translateY(-40px);
+ transform: translateY(-40px);
+}
+.humane p,
+.humane-libnotify p,
+.humane ul,
+.humane-libnotify ul {
+ margin: 0;
+ padding: 0;
+}
+.humane ul,
+.humane-libnotify ul {
+ list-style: none;
+}
+.humane.humane-libnotify-info,
+.humane-libnotify.humane-libnotify-info {
+ background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAABQCAYAAADYxx/bAAAABmJLR0QA/wD/AP+gvaeTAAAAMUlEQVQYlWNgYDB6ysTAwMDAxMDACCcYUFkMDEwMDEwMBNVhkxg65jGhmke6M6hgHgBSdgHnpZwADwAAAABJRU5ErkJggg==');
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0, rgba(0,0,50,0.9)), color-stop(1, rgba(0,0,100,0.9))) no-repeat;
+ background: -moz-linear-gradient(top, rgba(0,0,50,0.9) 0%, rgba(0,0,100,0.9) 100%) no-repeat;
+ background: -webkit-linear-gradient(top, rgba(0,0,50,0.9) 0%, rgba(0,0,100,0.9) 100%) no-repeat;
+ background: -ms-linear-gradient(top, rgba(0,0,50,0.9) 0%, rgba(0,0,100,0.9) 100%) no-repeat;
+ background: -o-linear-gradient(top, rgba(0,0,50,0.9) 0%, rgba(0,0,100,0.9) 100%) no-repeat;
+ background: linear-gradient(top, rgba(0,0,50,0.9) 0%, rgba(0,0,100,0.9) 100%) no-repeat;
+ *background-color: #030;
+}
+.humane.humane-libnotify-success,
+.humane-libnotify.humane-libnotify-success {
+ background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAABQCAYAAADYxx/bAAAABmJLR0QA/wD/AP+gvaeTAAAAMUlEQVQYlWNgMGJ4ysTAwMDAxMAIJxhQWQwMDEwMTKgS2NRhkxg65jGhmke6M6hhHgBS2QHn2LzhygAAAABJRU5ErkJggg==');
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0, rgba(0,50,0,0.9)), color-stop(1, rgba(0,100,0,0.9))) no-repeat;
+ background: -moz-linear-gradient(top, rgba(0,50,0,0.9) 0%, rgba(0,100,0,0.9) 100%) no-repeat;
+ background: -webkit-linear-gradient(top, rgba(0,50,0,0.9) 0%, rgba(0,100,0,0.9) 100%) no-repeat;
+ background: -ms-linear-gradient(top, rgba(0,50,0,0.9) 0%, rgba(0,100,0,0.9) 100%) no-repeat;
+ background: -o-linear-gradient(top, rgba(0,50,0,0.9) 0%, rgba(0,100,0,0.9) 100%) no-repeat;
+ background: linear-gradient(top, rgba(0,50,0,0.9) 0%, rgba(0,100,0,0.9) 100%) no-repeat;
+ *background-color: #030;
+}
+.humane.humane-libnotify-error,
+.humane-libnotify.humane-libnotify-error {
+ background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAADICAYAAAAp8ov1AAAABmJLR0QA/wD/AP+gvaeTAAAAPklEQVQokWMwYmB4ysTAwMCATjASFsOmBBvBRJ7x+O0g0wCS7CDTH/RwH7X9MVDuwyaG032D2M2UeIYO7gMAqt8C19Bn7+YAAAAASUVORK5CYII=');
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0, rgba(50,0,0,0.9)), color-stop(1, rgba(100,0,0,0.9))) no-repeat;
+ background: -moz-linear-gradient(top, rgba(50,0,0,0.9) 0%, rgba(100,0,0,0.9) 100%) no-repeat;
+ background: -webkit-linear-gradient(top, rgba(50,0,0,0.9) 0%, rgba(100,0,0,0.9) 100%) no-repeat;
+ background: -ms-linear-gradient(top, rgba(50,0,0,0.9) 0%, rgba(100,0,0,0.9) 100%) no-repeat;
+ background: -o-linear-gradient(top, rgba(50,0,0,0.9) 0%, rgba(100,0,0,0.9) 100%) no-repeat;
+ background: linear-gradient(top, rgba(50,0,0,0.9) 0%, rgba(100,0,0,0.9) 100%) no-repeat;
+ *background-color: #300;
+}
+.humane.humane-animate,
+.humane-libnotify.humane-libnotify-animate {
+ opacity: 1;
+ -moz-transform: translateY(0);
+ -webkit-transform: translateY(0);
+ -ms-transform: translateY(0);
+ -o-transform: translateY(0);
+ transform: translateY(0);
+}
+.humane.humane-animate:hover,
+.humane-libnotify.humane-libnotify-animate:hover {
+ opacity: 0.2;
+}
+.humane.humane-animate,
+.humane-libnotify.humane-libnotify-js-animate {
+ opacity: 1;
+ -moz-transform: translateY(0);
+ -webkit-transform: translateY(0);
+ -ms-transform: translateY(0);
+ -o-transform: translateY(0);
+ transform: translateY(0);
+}
+.humane.humane-animate:hover,
+.humane-libnotify.humane-libnotify-js-animate:hover {
+ opacity: 0.2;
+ filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=20);
+}
diff --git a/lib/Korap/Plugin/Notifications/Humane/original.css b/lib/Korap/Plugin/Notifications/Humane/original.css
new file mode 100644
index 0000000..60393de
--- /dev/null
+++ b/lib/Korap/Plugin/Notifications/Humane/original.css
@@ -0,0 +1,72 @@
+html,
+body {
+ min-height: 100%;
+}
+.humane,
+.humane-original {
+ position: fixed;
+ -moz-transition: all 0.2s ease-out;
+ -webkit-transition: all 0.2s ease-out;
+ -ms-transition: all 0.2s ease-out;
+ -o-transition: all 0.2s ease-out;
+ transition: all 0.2s ease-out;
+ z-index: 100000;
+ filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100);
+}
+.humane,
+.humane-original {
+ font-family: Ubuntu, Verdana, sans-serif;
+ line-height: 40px;
+ font-size: 25px;
+ top: 25%;
+ left: 25%;
+ opacity: 0;
+ width: 50%;
+ min-height: 40px;
+ padding: 10px;
+ text-align: center;
+ background-color: #000;
+ color: #fff;
+ -webkit-border-radius: 15px;
+ border-radius: 15px;
+}
+.humane p,
+.humane-original p,
+.humane ul,
+.humane-original ul {
+ margin: 0;
+ padding: 0;
+}
+.humane ul,
+.humane-original ul {
+ list-style: none;
+}
+.humane.humane-original-info,
+.humane-original.humane-original-info {
+ background-color: #030;
+}
+.humane.humane-original-success,
+.humane-original.humane-original-success {
+ background-color: #030;
+}
+.humane.humane-original-error,
+.humane-original.humane-original-error {
+ background-color: #300;
+}
+.humane.humane-animate,
+.humane-original.humane-original-animate {
+ opacity: 0.8;
+}
+.humane.humane-animate:hover,
+.humane-original.humane-original-animate:hover {
+ opacity: 0.6;
+}
+.humane.humane-js-animate,
+.humane-original.humane-original-js-animate {
+ opacity: 0.8;
+}
+.humane.humane-js-animate:hover,
+.humane-original.humane-original-js-animate:hover {
+ opacity: 0.6;
+ filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=60);
+}
diff --git a/lib/Korap/Plugin/Notifications/Humane/readme.md b/lib/Korap/Plugin/Notifications/Humane/readme.md
new file mode 100644
index 0000000..cf4938b
--- /dev/null
+++ b/lib/Korap/Plugin/Notifications/Humane/readme.md
@@ -0,0 +1,85 @@
+# humane.js
+This project was heavily inspired by [humanmsg](http://code.google.com/p/humanmsg/) project for jQuery. I really
+liked the project but I wanted to remove the jQuery dependency, add support for CSS transitions, and have more
+control over the timing.
+
+## About
+humane.js tries to be as unobtrusive as possible to the user experience while providing helpful information that is
+clear and grabs the users attention. It is framework independent. Customizable.
+
+## Setup
+Setup is simple:
+
+ - Download tar/zip
+ - Select a [theme](https://github.com/wavded/humane-js/wiki/Themes) from `themes` dir.
+ - Include the theme CSS in your page
+ - Include `humane.min.js` in your page
+
+## Demo/Usage
+
+You can see a [demo and usage here](http://wavded.github.com/humane-js/)
+
+## Custom Themes
+
+Got a neat theme/animation, love to see it. View `theme-src/bigbox.styl` for an template to get started (uses [Stylus](http://learnboost.github.com/stylus/) w/ Nib and Canvas).
+
+To get setup with Stylus use [npm](http://npmjs.org):
+
+```sh
+(sudo) npm install -g stylus nib canvas
+```
+
+With Stylus installed you can watch for changes and compile into CSS by running:
+
+```sh
+make watch
+```
+
+## Desktop and Mobile Browser Support
+
+humane.js has been tested for the following browsers.
+
+ - Internet Explorer 7+
+ - Firefox 3+
+ - Chrome 9+
+ - Safari 3+
+ - Opera 10+
+ - iOS 4+
+ - Android 2+
+
+## AMD and Node.js Support
+
+humane.js works for AMD systems like [require.js](http://requirejs.org/) and within Node.js CommonJS module system like [browserify](https://github.com/substack/node-browserify).
+
+## Contributers
+
+Many thanks to the JS/Browser wizards that helped make this better, community rocks!
+
+- @bga_ (Alexander)
+- @joseanpg (Jose)
+- @OiNutter (Will McKenzie)
+- @ianmassey (Ian Massey)
+
+## License
+
+(The MIT License)
+
+Copyright (c) 2011 Marc Harter <wavded@gmail.com>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+'Software'), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/lib/Korap/Search.pm b/lib/Korap/Search.pm
new file mode 100644
index 0000000..e548ace
--- /dev/null
+++ b/lib/Korap/Search.pm
@@ -0,0 +1,14 @@
+package Korap::Search;
+use Mojo::Base 'Mojolicious::Controller';
+
+# This action will render a template
+sub remote {
+ my $c = shift;
+
+ # Render template "example/welcome.html.ep" with message
+ $c->render(template => 'search');
+};
+
+
+
+1;