Ado

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN

0.43 2014-05-25
    - Default page now has a Bulgarian variant.

0.42 2014-05-18
    - Fixed typos and improved POD.
    - Added Ado::Plugin::I18n to the list of the end-user
      features at the bottom of the home page.
    - Created and used templates/partials/logo.html.ep.
    - Created embedded template languages_menu.html.ep in Ado::Plugin::I18n
      and used it on the home page. This is a usage example.
    - Added jQuery Cookie Plugin v1.4.1.
    - Added some flag icons from http://www.famfamfam.com.
    - Upgraded to Mojolicious 4.99.
    - Upgraded to Semantic UI 0.17.0

0.41 2014-05-11
    - Translated intro.md. to Bulgarian.
    - Menu items in adobar.html.ep now are only icons.
    - Implemented Ado::Plugin::I18n.
      First lexicons are in English and Bulgarian.
    - Upgraded to Mojolicious 4.98.

etc/ado.conf  view on Meta::CPAN


        #TODO: report problem with easing when loading separate js components
        $sui_path . '/transition.min.js',
    ]
);

{

    # Hypnotoad Settings (optimized for blocking operations)
    # See /perldoc/Mojo/Server/Hypnotoad#SETTINGS
    # and /perldoc/Mojolicious/Guides/Cookbook#Hypnotoad
    hypnotoad => {

        #listen  => ['http://*:9090'],
        #proxy   => 1,
        workers => 20,
        clients => 1,
    },
    session => {

        #Type of the session this application will use

lib/Ado/Build.pm  view on Meta::CPAN


=head2 do_create_readme

Creates the README file from C<lib/Ado/Manual.pod>.

=head1 SEE ALSO

L<Ado::BuildPlugin>,
L<Module::Build::API>,
L<Module::Build::Authoring>,
L<Module::Build::Cookbook/ADVANCED_RECIPES>,
Build.PL in Ado distribution directory.

=head1 AUTHOR

Красимир Беров (Krasimir Berov)

=head1 COPYRIGHT AND LICENSE

Copyright 2013-2014 Красимир Беров (Krasimir Berov).

lib/Ado/Command/generate/adoplugin.pm  view on Meta::CPAN

Run this command.

=head1 SEE ALSO

L<Mojolicious::Command::generate::plugin>,
L<Ado::Command::generate::crud>,
L<Ado::Command::generate::apache2vhost>,
L<Ado::Command::generate::apache2htaccess>, L<Ado::Command::generate>,
L<Mojolicious::Command::generate>, L<Getopt::Long>,
L<Ado::Command> L<Ado::Manual>,
L<Mojolicious>, L<Mojolicious::Guides::Cookbook/DEPLOYMENT>

=head1 AUTHOR

Красимир Беров (Krasimir Berov)

=head1 COPYRIGHT AND LICENSE

Copyright 2014 Красимир Беров (Krasimir Berov).

This program is free software, you can redistribute it and/or

lib/Ado/Command/generate/apache2htaccess.pm  view on Meta::CPAN

Run this command. Returns C<$self>.

=head1 SEE ALSO

L<Ado::Plugin::Routes>,
L<Apache deployment|https://github.com/kraih/mojo/wiki/Apache-deployment>,
L<Apache - Upgrading to 2.4 from 2.2|http://httpd.apache.org/docs/2.4/upgrading.html>,
L<Ado::Command::generate::apache2vhost>,
L<Ado::Command::generate>, L<Getopt::Long>,
L<Ado::Command> L<Ado::Manual>,
L<Mojolicious>, L<Mojolicious::Guides::Cookbook/DEPLOYMENT>,
L<Mojo::Server::FastCGI>.

=cut

lib/Ado/Command/generate/apache2vhost.pm  view on Meta::CPAN


  $vhost->run(@ARGV);

Run this command. Returns C<$self>.


=head1 SEE ALSO

L<Apache deployment|https://github.com/kraih/mojo/wiki/Apache-deployment>,
L<Apache - Upgrading to 2.4 from 2.2|http://httpd.apache.org/docs/2.4/upgrading.html>,
L<Mojolicious::Guides::Cookbook>,
L<Ado::Command::generate::apache2htaccess>,
L<Mojolicious::Command::generate>, L<Getopt::Long>,
L<Ado::Command> L<Ado::Manual>,
L<Mojolicious>, L<Mojolicious::Guides::Cookbook/DEPLOYMENT>

=cut

lib/Ado/Command/generate/crud.pm  view on Meta::CPAN


Run this command.

=head1 SEE ALSO

L<Ado::Command::generate::adoplugin>,
L<Ado::Command::generate::apache2vhost>,
L<Ado::Command::generate::apache2htaccess>, L<Ado::Command::generate>,
L<Mojolicious::Command::generate>, L<Getopt::Long>,
L<Ado::Command> L<Ado::Manual>,
L<Mojolicious>, L<Mojolicious::Guides::Cookbook/DEPLOYMENT>

=head1 AUTHOR

Красимир Беров (Krasimir Berov)

=head1 COPYRIGHT AND LICENSE

Copyright 2014 Красимир Беров (Krasimir Berov).

This program is free software, you can redistribute it and/or

lib/Ado/Manual/FiveMinutes.pod  view on Meta::CPAN

Look at the source of L<Ado::Control::Articles> to see how it works. Go to
L<http://127.0.0.1:3000/> and play more or visit the links in the L</SEE ALSO>
section. Now you can fork the project on
L<Github|https://github.com/kberov/Ado>, improve C<menu.html.ep> to
automatically traverse the articles directory and generate the list of
articles, then make a merge request. You just contributed to the project.

=head1 SEE ALSO

L<Ado::Manual>, L<Ado>, L<Mojolicious::Guides>,
L<Mojolicious::Guides::Cookbook/DEPLOYMENT>, L<Ado::Command::generate::apache2htaccess>

=head1 COPYRIGHT AND LICENSE

Copyright 2013-2015 Красимир Беров (Krasimir Berov).

This program is free software, you can redistribute it and/or
modify it under the terms of the
GNU Lesser General Public License v3 (LGPL-3.0).

lib/Ado/Manual/Installation.pod  view on Meta::CPAN


  mkdir ~/ado && cd ~/ado && wget https://github.com/kberov/Ado/archive/v0.87.zip
  unzip v0.87.zip
  Ado-0.87/bin/ado daemon
  #Server available at http://127.0.0.1:3000

=head2 SUMMARY

Ado can be installed and deployed in many different ways. At the end it is
simply a Perl module which happen to be a Mojolicious application. For
inspiration, please read  L<Mojolicious::Guides::Cookbook/DEPLOYMENT> and maybe
try L<Ado::Command::generate::apache2htaccess>. Now you can follow the
instructions, found on the home-page
L<http://127.0.0.1:3000|http://127.0.0.1:3000>. But to grow with Ado, you should
install and create some plugins. See L<Ado::Manual::Plugins>.

=head1 SEE ALSO

L<Ado::Manual>, L<Ado>, L<Mojolicious::Guides>,
L<Module::Build::Cookbook/prefix_vs_install_base>

=head1 COPYRIGHT AND LICENSE

Copyright 2013-2015 Красимир Беров (Krasimir Berov).

This program is free software, you can redistribute it and/or
modify it under the terms of the
GNU Lesser General Public License v3 (LGPL-3.0).

lib/Ado/Plugin/I18n.pm  view on Meta::CPAN

The following options can be set in C<etc/ado.conf> or in C<etc/plugins/i18n.conf>.
You have to create first C<etc/plugins/i18n.conf> so Ado can pick it up.
You can enable all supported methods to detect the language in your application.

The methods which will be used to detect and set the current
language are as follows:

  1. language_from_route,   eg. /bg/controller/action
  2. language_from_host,    eg. fr.example.com
  3. language_from_param,   eg. ?language=de
  4. language_from_cookie,  eg. Cookie: language=bg;
  5. language_from_headers, eg. Accept-Language: bg,fr;q=0.8,en-us;q=0.5,en;q=0.3

Just be careful not to try to set the language in one request using two different
methods eg. C</bg/controller/action?language=de>.


=head2 default_language

The default value is C<en>. This language is used when Ado is not able to detect
the language using any of the methods enabled by the options below.

lib/Ado/Plugin/I18n.pm  view on Meta::CPAN


This is the fifth option that will be checked if enabled and if the language is
not yet detected using some of the previous methods.
It is best to keep this option enabled.
Default value is 1.

=head2 language_param

    #language_param=> 'l'
    current language is <%= $l %>
    Cookie: l=bg;
    #language_param=> 'lang'
    current language is <%= $lang %>
    Cookie: lang=bg;

The name of the parameter(key) used in C<language_from_param>, C<language_from_route>
and C<language_from_cookie>. this is also the key used in the C<$c-E<gt>stash>.
Default value is "language".

=head2 namespace

The namespace used for language classes.
Default value is L<Ado::I18n>.
You rarely will want to change this.

lib/Ado/Plugin/I18n.pm  view on Meta::CPAN

%   foreach my $l(@languages){
%   my $active = $l eq $language ? 'active ' : '';
  <a class="<%="$l $active" %>button item"
    href="<%= url_for; %>" data-content="<%= l($l) %>"
    data-language="<%= $l %>"><%=l($l)%></a>
%   }
%   my $languages_css_selectors = join(', ', map("#language_menu a.$_", @languages));
  <script src="/js/jquery.cookie.js"></script>
  <script>
    $('<%=$languages_css_selectors%>').click(function(){
        $.removeCookie('<%=$language_param%>', { path: '/' });
        $.cookie('<%=$language_param%>',$(this).data('language'),{
            expires: 30, path: '/' });
    });
  </script>
% }
  </div><!-- end div class="dropdown menu" -->
</div><!-- end div class="ui simple dropdown item" -->
</div>
<!-- language_menu end -->

lib/Ado/Sessions.pm  view on Meta::CPAN

        default_expiration => 86400,
    }
  }

  #In Ado.pm:
  has sessions => sub { Ado::Sessions::get_instance(shift->config) };


=head2 cookie_domain

Cookie domain accessor

=head2 cookie_name

Cookie name accessor

=head2 cookie_path

Cookie path accessor

=head2 default_expiration

Cookie default expiration accessor

=head2 generate_id

Session id generator

=head2 get_instance

Factory method for creating Ado session instance

=head2 prepare_load

Shares common logic which is compatible with L<Mojolicious::Sessions>.
The storage implementation class should call this method after it loads
the session from the respective storage.

    $self->prepare_load($c, $session);

=head2 secure

Cookie is secure, flag

=head2 prepare_store

Shares common logic which is compatible with L<Mojolicious::Sessions>.
The storage implementation class should call this method before it stores
the session to the the respective storage.
Returns the session id and the session ready to be serialized
and base 64 encoded.

    my ($id, $session) = $self->prepare_store($c);

public/doc/bg/intro.md  view on Meta::CPAN


Ето как изглежда една система, базирана на Адо като архитектура:

![Съставни части на Адо](/img/Ado-Building-Blocks.png "Съставни части на Адо")

##Инсталация/Разполагане
Начинът на инсталиране, който ви дава най-голяма гъвкавост, е на командния ред.
Силно се препоръчва да ползвате отделна дистрибуция на Perl предназначена специално за целта - не тази, която идва с операционната ви систÐ...
ActivePerl или perlbrew са добър избор.

Всички сценарии описани на адрес [Mojolicious/Guides/Cookbook#DEPLOYMENT](http://mojolicio.us/perldoc/Mojolicious/Guides/Cookbook#DEPLOYMENT)
са валидни за Адо, като може да направите и ваша собствена комбинация.

##REST API[^restbg]
Адо се стреми към строго разпределение на отговорностите (MVC[^mvcbg]).
Най-добрият начин да се постигне това е като напълно се отдели програмният код, 
работещ при клиента (в браузъра) от кода, работещ на сървъра. Адо е идеално пригоден
за тази цел благодарение на Mojolicious. Всеки ресурс е достъпен чрез програмния 
REST интерфейс. Ние следим от близо и надграждаме върху препоръките от
"Добри практики за услуги, базирани на REST" на www.RestApiTutorial.com.

public/doc/en/intro.md  view on Meta::CPAN


Here is how an Ado system looks like from architectural point of view:

![Ado building blocks](/img/Ado-Building-Blocks.png "Ado building blocks")

##Installation/Deployment
The most flexible way to install Ado is manually on the command line.
It is highly recommended to have a separate Perl distribution (not the one that comes with your OS).
ActivePerl or perlbrew are both fine. 

All deployment scenarios described at [Mojolicious/Guides/Cookbook#DEPLOYMENT](http://mojolicio.us/perldoc/Mojolicious/Guides/Cookbook#DEPLOYMENT)
are possible and specific custom deployments can be done.

Ado is not actively tested under Windows, but there is an [Ado PPM package](http://code.activestate.com/ppm/Ado/) for Mac OSX, Linux and Windows maintained by Active State.

##REST API[^rest]
Ado strives for strict separation of concerns (MVC[^2]). The best way to achieve this is to fully separate the client code from the server code. Ado is ideally suited for the purpose thanks to Mojolicious. Every resource is accessible via the REST AP...

##Roadmap
Below are the main activities considered mandatory for implementation to reach version 1.00.

public/js/jquery.cookie.js  view on Meta::CPAN

/*!
 * jQuery Cookie Plugin v1.4.1
 * https://github.com/carhartl/jquery-cookie
 *
 * Copyright 2013 Klaus Hartl
 * Released under the MIT license
 */
(function (factory) {
	if (typeof define === 'function' && define.amd) {
		// AMD
		define(['jquery'], factory);
	} else if (typeof exports === 'object') {

public/js/jquery.cookie.js  view on Meta::CPAN

	var pluses = /\+/g;

	function encode(s) {
		return config.raw ? s : encodeURIComponent(s);
	}

	function decode(s) {
		return config.raw ? s : decodeURIComponent(s);
	}

	function stringifyCookieValue(value) {
		return encode(config.json ? JSON.stringify(value) : String(value));
	}

	function parseCookieValue(s) {
		if (s.indexOf('"') === 0) {
			// This is a quoted cookie as according to RFC2068, unescape...
			s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
		}

		try {
			// Replace server-side written pluses with spaces.
			// If we can't decode the cookie, ignore it, it's unusable.
			// If we can't parse the cookie, ignore it, it's unusable.
			s = decodeURIComponent(s.replace(pluses, ' '));
			return config.json ? JSON.parse(s) : s;
		} catch(e) {}
	}

	function read(s, converter) {
		var value = config.raw ? s : parseCookieValue(s);
		return $.isFunction(converter) ? converter(value) : value;
	}

	var config = $.cookie = function (key, value, options) {

		// Write

		if (value !== undefined && !$.isFunction(value)) {
			options = $.extend({}, config.defaults, options);

			if (typeof options.expires === 'number') {
				var days = options.expires, t = options.expires = new Date();
				t.setTime(+t + days * 864e+5);
			}

			return (document.cookie = [
				encode(key), '=', stringifyCookieValue(value),
				options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
				options.path    ? '; path=' + options.path : '',
				options.domain  ? '; domain=' + options.domain : '',
				options.secure  ? '; secure' : ''
			].join(''));
		}

		// Read

		var result = key ? undefined : {};

public/js/jquery.cookie.js  view on Meta::CPAN

			if (!key && (cookie = read(cookie)) !== undefined) {
				result[name] = cookie;
			}
		}

		return result;
	};

	config.defaults = {};

	$.removeCookie = function (key, options) {
		if ($.cookie(key) === undefined) {
			return false;
		}

		// Must not alter options, thus extending a fresh object...
		$.cookie(key, '', $.extend({}, options, { expires: -1 }));
		return !$.cookie(key);
	};

}));

t/plugin/i18n-02.t  view on Meta::CPAN

use Mojo::Base -strict;
use Test::More;
use Test::Mojo;
use List::Util qw(first);
my $t   = Test::Mojo->new('Ado');
my $app = $t->app;

#warn $app->dumper(\%ENV);

#$config->{language_from_cookie}
$t->get_ok('/', {Cookie => Mojo::Cookie::Request->new(name => language => value => 'bg')})
  ->status_is(200)->text_is(
    '#login_form label[for="login_name"]',
    'Потребител',
    '/ Cookie: language=bg content'
  );

$t->get_ok('/test')
  ->content_like(qr'Здрасти, Guest!', '/:controller Cookie: language=bg content');

my $jar = $t->ua->cookie_jar;
my $cookie = first { $_->name eq 'language' } @{$jar->all};
$cookie->value('en');
$t->get_ok('/test/l10n')
  ->content_like(qr'Hello Guest,', '/:controller/:action Cookie: language=en content');

#$cookie = first {$_->name eq 'language'} $jar->all;
#$cookie->value('bg');
$t->get_ok('/test/bgl10n')
  ->content_like(qr'Здрасти, Guest!', 'language explicitly set in action');

$cookie = first { $_->name eq 'language' } @{$jar->all};
$cookie->value('is');
$t->get_ok('/')->status_is(200)
  ->text_is('#login_form label[for="login_name"]', 'User', '/:language - fallback content');

t/sessions/database.t  view on Meta::CPAN

my $cookie_name = $t->app->sessions->cookie_name;

is($cookie_name, 'ado_session_id', '$cookie_name is ado_session_id');

# Create new SID
$t->get_ok('/test', 'created new session ok');
my $sid = $t->tx->res->cookie($cookie_name)->value;
ok $sid, "new sid $sid ok";

$t->get_ok("/");
is $sid, $t->tx->res->cookie($cookie_name)->value, 'Cookie $sid ok';

#default_expiration
$t->get_ok("/");
my $default_expiration = $t->app->sessions->default_expiration;
my $expires            = $t->tx->res->cookie($cookie_name)->expires;

#may differ with one second
ok($expires <= gmtime(time + $default_expiration)->epoch, '$default_expiration is ok');

#session expired

t/sessions/file.t  view on Meta::CPAN


my $cookie_name = $t->app->config('session')->{options}{cookie_name};
is($cookie_name, 'ado_session_file', '$cookie_name is ado_session_file');

# Create new SID
$t->get_ok('/test', 'created new session ok');
my $sid = $t->tx->res->cookie($cookie_name)->value;
ok $sid, "new sid $sid ok";

$t->get_ok("/");
is $sid, $t->tx->res->cookie($cookie_name)->value, 'Cookie $sid ok';

#default_expiration
$t->get_ok("/");
my $default_expiration = $t->app->sessions->default_expiration;
my $expires            = $t->tx->res->cookie($cookie_name)->expires;
my $equal              = $expires - gmtime(time + $default_expiration)->epoch;

#may differ with one second
ok($equal == 0 || $equal == -1, '$default_expiration is ok');

t/sessions/mojolicious.t  view on Meta::CPAN

$t->app->config(session => {type => 'mojo', options => {cookie_name => 'ado_session_mojo'}});
my $cookie_name = $t->app->config('session')->{options}{cookie_name};

# Create new SID
$t->get_ok('/добре/ок');
my $sid = $t->tx->res->cookie($cookie_name)->value;
ok $sid, 'new sid $sid ok';


$t->get_ok("/");
is $sid, $t->tx->res->cookie($cookie_name)->value, 'Cookie $sid ok';

#default_expiration
$t->get_ok("/");
my $default_expiration = $t->app->sessions->default_expiration;
my $expires            = $t->tx->res->cookie($cookie_name)->expires;
my $equal = Time::Piece->strptime($expires)->epoch - gmtime(time + $default_expiration)->epoch;

#may differ with one second
ok($equal == 0 || $equal == -1, '$default_expiration is ok');



( run in 0.713 second using v1.01-cache-2.11-cpan-4e96b696675 )