Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

jumpstarts simple apps

  • Loading branch information...
commit dcb697b000f22960be3a7daf82505de8c838b32c 0 parents
Robert »phaylon« Sedlacek authored
64 lib/ReactionX/Jumpstart.pm
@@ -0,0 +1,64 @@
+use MooseX::Declare;
+
+class ReactionX::Jumpstart
+ with ReactionX::Jumpstart::Generating
+ with ReactionX::Jumpstart::Namespacing
+ with ReactionX::Jumpstart::SubBuilding
+ with ReactionX::Jumpstart::Stashing {
+
+ use MooseX::Types::Moose qw( Str Object );
+ use Path::Class qw( dir );
+
+ use signatures;
+
+ use aliased 'ReactionX::Jumpstart::Application';
+ use aliased 'ReactionX::Jumpstart::Config';
+
+
+ has application_builder => (
+ isa => Object,
+ required => 1,
+ lazy_build => 1,
+ handles => { build_application => 'JUMPSTART' },
+ );
+
+ has config_builder => (
+ isa => Object,
+ required => 1,
+ lazy_build => 1,
+ handles => { build_config => 'JUMPSTART' },
+ );
+
+
+ method JUMPSTART {
+
+ $self->build_application;
+ $self->build_config;
+ }
+
+ method find_root_path {
+
+ my $project = $self->project_namespace;
+ $project =~ s{::}{-}g;
+
+ return dir( 'test', lc $project );
+ }
+
+ method _build_application_builder {
+
+ my $project = $self->project_namespace;
+ my $ui = $self->ui_namespace;
+
+ $self->set_stash(
+ project_namespace => $project,
+ ui_namespace => $ui,
+ );
+
+ return $self->new_sub_builder(Application);
+ }
+
+ method _build_config_builder {
+
+ return $self->new_sub_builder(Config);
+ }
+}
80 lib/ReactionX/Jumpstart/Application.pm
@@ -0,0 +1,80 @@
+use MooseX::Declare;
+
+class ReactionX::Jumpstart::Application
+ with ReactionX::Jumpstart::Generating
+ with ReactionX::Jumpstart::SubBuilding
+ with ReactionX::Jumpstart::Namespacing
+ with ReactionX::Jumpstart::Stashing {
+
+
+ use MooseX::Types::Moose qw( Str Bool Object );
+ use Catalyst::Runtime;
+ use Reaction;
+
+ use aliased 'ReactionX::Jumpstart::Controller::Root';
+ use aliased 'ReactionX::Jumpstart::View';
+
+
+ has application_name => (
+ traits => [qw( ReactionX::Jumpstart::Meta::Attribute::Trait::Prompted )],
+ is => 'rw',
+ isa => Str,
+ question => 'Descriptive name of the application?',
+ defaults_to => sub { my $name = $_[0]->project_namespace; $name =~ s{::}{-}g; $name },
+ );
+
+ has root_controller_is_built => (
+ traits => [qw( ReactionX::Jumpstart::Meta::Attribute::Trait::Prompted )],
+ is => 'rw',
+ isa => Bool,
+ question => 'Create a Root Controller?',
+ help_info => "The Controller managing '/'",
+ defaults_to => 1,
+ );
+
+ has root_controller_builder => (
+ isa => Object,
+ required => 1,
+ lazy_build => 1,
+ handles => { build_root_controller => 'JUMPSTART' },
+ );
+
+ has view_builder => (
+ isa => Object,
+ required => 1,
+ lazy_build => 1,
+ handles => { build_view => 'JUMPSTART' },
+ );
+
+
+ method JUMPSTART {
+
+ my $application_package = join '::', $self->project_namespace, $self->ui_namespace;
+ my $application_name = $self->application_name;
+
+ $self->set_stash(
+ application_package => $application_package,
+ application_name => $application_name,
+ );
+
+ $self->build_package(
+ package => $application_package,
+ dist => 'ReactionX-Jumpstart',
+ template => 'application',
+ vars => {
+ catalyst_version => Catalyst::Runtime->VERSION,
+ reaction_version => Reaction->VERSION,
+ },
+ );
+
+ $self->build_view;
+
+ if ($self->root_controller_is_built) {
+ $self->build_root_controller;
+ }
+ }
+
+ method _build_root_controller_builder { $self->new_sub_builder(Root) }
+
+ method _build_view_builder { $self->new_sub_builder(View) }
+}
25 lib/ReactionX/Jumpstart/Config.pm
@@ -0,0 +1,25 @@
+use MooseX::Declare;
+
+class ReactionX::Jumpstart::Config
+ with ReactionX::Jumpstart::Generating
+ with ReactionX::Jumpstart::Stashing
+ with ReactionX::Jumpstart::Namespacing {
+
+
+ use Catalyst::Utils;
+
+
+ method JUMPSTART {
+
+ my $config_file = $self->path_to_file(
+ 'etc',
+ Catalyst::Utils::appprefix(join '::', $self->project_namespace, $self->ui_namespace) . '.conf',
+ );
+
+ $self->build_file(
+ file => $config_file,
+ dist => 'ReactionX-Jumpstart',
+ template => 'application.conf',
+ );
+ }
+}
90 lib/ReactionX/Jumpstart/Controller.pm
@@ -0,0 +1,90 @@
+use MooseX::Declare;
+
+class ReactionX::Jumpstart::Controller
+ with ReactionX::Jumpstart::Namespacing
+ with ReactionX::Jumpstart::Generating
+ with ReactionX::Jumpstart::SubBuilding
+ with ReactionX::Jumpstart::Stashing {
+
+ use MooseX::Types::Moose qw( Str Bool Object );
+ use Data::Dump qw( pp );
+
+
+ has controller_namespace => (
+ traits => [qw( ReactionX::Jumpstart::Meta::Attribute::Trait::Prompted )],
+ is => 'rw',
+ isa => Str,
+ question => 'Name of the Controller?',
+ help_info => sub {
+ sprintf 'example: %s for %s::%s::Controller::%s',
+ $_[1] || 'Foo',
+ $_[0]->project_namespace,
+ $_[0]->ui_namespace,
+ $_[1] || 'Foo',
+ },
+ );
+
+ has base_controller_namespace => (
+ traits => [qw( ReactionX::Jumpstart::Meta::Attribute::Trait::Prompted )],
+ is => 'rw',
+ isa => Str,
+ question => 'ClassName of base Controller?',
+ defaults_to => 'Reaction::UI::Controller',
+ );
+
+ has base_chained_to => (
+ traits => [qw( ReactionX::Jumpstart::Meta::Attribute::Trait::Prompted )],
+ is => 'rw',
+ isa => Str,
+ question => 'To what action is the base action chained?',
+ help_info => 'via private path, e.g. /foo/bar',
+ defaults_to => '/',
+ );
+
+ has base_path_part => (
+ traits => [qw( ReactionX::Jumpstart::Meta::Attribute::Trait::Prompted )],
+ is => 'rw',
+ isa => Str,
+ question => 'What is the base (public) path part for this Controller?',
+ defaults_to => sub { lc( ( split /::/, $_[0]->base_controller_namespace )[-1] ) },
+ );
+
+
+ method JUMPSTART {
+
+ my $controller_namespace = join '::',
+ $self->project_namespace,
+ $self->ui_namespace,
+ 'Controller',
+ $self->controller_namespace;
+
+ my $base_namespace = $self->base_controller_namespace;
+ my $base_chained_to = $self->base_chained_to;
+ my $base_path_part = $self->base_path_part;
+ my $config_partial = $self->render_config({});
+
+ $self->build_controller_package(
+ package => $controller_namespace,
+ dist => 'ReactionX-Jumpstart',
+ template => 'controller',
+ vars => {
+ controller_package => $controller_namespace,
+ controller_base => $base_namespace,
+ controller_config => $config_partial,
+ base_chained_to => $base_chained_to,
+ base_path_part => $base_path_part,
+ }
+ );
+ }
+
+ method render_config (HashRef $config) {
+
+ return join "\n", map {
+ sprintf '%s => %s,',
+ pp($_),
+ pp($config->{ $_ }),
+ } keys %$config;
+ }
+
+ method build_controller_package (%args) { $self->build_package(%args) }
+}
105 lib/ReactionX/Jumpstart/Controller/Root.pm
@@ -0,0 +1,105 @@
+use MooseX::Declare;
+
+class ReactionX::Jumpstart::Controller::Root
+ extends ReactionX::Jumpstart::Controller {
+
+
+ use MooseX::Types::Moose qw( Str Bool Object );
+
+ use aliased 'ReactionX::Jumpstart::ViewGroup';
+
+
+ has '+controller_namespace' => (defaults_to => 'Root');
+
+ has site_layout_is_pushed => (
+ traits => [qw( ReactionX::Jumpstart::Meta::Attribute::Trait::Prompted )],
+ is => 'rw',
+ isa => Bool,
+ question => 'Do you want a base action to push the SiteLayout ViewPort?',
+ defaults_to => 1,
+ );
+
+ has site_layout_is_customized => (
+ traits => [qw( ReactionX::Jumpstart::Meta::Attribute::Trait::Prompted )],
+ is => 'rw',
+ isa => Bool,
+ question => 'Do you want a customized SiteLayout ViewPort, Widget and LayoutSet?',
+ defaults_to => 1,
+ );
+
+ has site_layout_group_builder => (
+ isa => Object,
+ required => 1,
+ lazy_build => 1,
+ handles => { build_site_layout_group => 'JUMPSTART' },
+ );
+
+
+ method _build_base_controller_namespace { 'Reaction::UI::Controller::Root' }
+
+ method _build_base_chained_to { '/' }
+
+ method _build_base_path_part { '' }
+
+ method _build_site_layout_group_builder {
+
+ return $self->new_sub_builder(ViewGroup,
+ additional => {
+ view_group_name => 'SiteLayout',
+ viewport_builder_args => {
+ viewport_base_class => 'Reaction::UI::ViewPort::SiteLayout',
+ },
+ widget_builder_args => {
+ widget_base_class => 'Reaction::UI::Widget::SiteLayout',
+ },
+ layout_set_builder_args => {
+ base_layout_set_name => 'site_layout',
+ layout_set_is_extension => 1,
+ widget_name_is_explicit => 1,
+ },
+ },
+ );
+ }
+
+
+ around render_config (HashRef $config) {
+
+ return $self->$orig({
+ %$config,
+ namespace => '',
+ view_name => $self->stash->{site_view_name},
+ });
+ }
+
+ around build_controller_package (%args) {
+
+ my $push_site_layout = $args{vars}{site_layout_is_pushed}
+ ||= $self->site_layout_is_pushed;
+
+ if ($push_site_layout) {
+
+ my $is_customized = $args{vars}{site_layout_is_customized}
+ ||= $self->site_layout_is_customized;
+
+ if ($is_customized) {
+
+ $self->build_site_layout_group;
+ $self->set_stash(site_layout_class => join '::',
+ $self->project_namespace,
+ $self->ui_namespace,
+ 'ViewPort::SiteLayout',
+ );
+ }
+ else {
+
+ $self->set_stash(site_layout_class => 'Reaction::UI::ViewPort::SiteLayout');
+ }
+ }
+
+ return $self->$orig(%args);
+ }
+
+ after JUMPSTART {
+ $self->set_stash(root_controller_namespace => $self->controller_namespace);
+ }
+}
82 lib/ReactionX/Jumpstart/Generating.pm
@@ -0,0 +1,82 @@
+use MooseX::Declare;
+
+role ReactionX::Jumpstart::Generating with ReactionX::Jumpstart::Stashing {
+
+ use Class::Inspector;
+ use Template;
+ use File::ShareDir qw( dist_file );
+ use MooseX::Types::Path::Class qw( Dir );
+ use Carp qw( croak );
+
+ use signatures;
+
+
+ requires qw( JUMPSTART );
+
+
+ has root_path => (
+ is => 'ro',
+ isa => Dir,
+ required => 1,
+ lazy => 1,
+ coerce => 1,
+ default => sub ($self) {
+
+ if (my $method = $self->can('find_root_path')) {
+ return $self->$method;
+ }
+
+ croak "root_path attribute is required for ${\ref $self}";
+ },
+ );
+
+ has _tt_engine => (
+ is => 'rw',
+ isa => 'Template',
+ required => 1,
+ lazy_build => 1,
+ handles => { _process_template => 'process' },
+ );
+
+
+ method _build__tt_engine {
+
+ return Template->new(
+ ABSOLUTE => 1,
+ RELATIVE => 1,
+ );
+ }
+
+ method build_package (Str :$package!, Str :$template!, Str :$dist!, HashRef :$vars = {}) {
+
+ my $package_filename = $self->path_to_file('lib', Class::Inspector->filename($package));
+ my $template_filename = dist_file($dist, "$template.tt");
+
+ print " -> writing package $package\n";
+
+ $self->_process_template("$template_filename", +{ %{ $self->stash }, %$vars }, "$package_filename");
+ }
+
+ method build_file (Str | Path::Class::File :$file!, Str :$template!, Str :$dist!, HashRef :$vars = {}) {
+
+ my $template_filename = dist_file($dist, "$template.tt");
+
+ print " -> writing file $file\n";
+
+ $self->_process_template("$template_filename", +{ %{ $self->stash }, %$vars }, "$file");
+ }
+
+ method mkpath (@dir) {
+
+ my $dir = $self->path_to_dir(@dir);
+
+ print " -> creating directory $dir\n";
+ $dir->mkpath;
+
+ return $dir;
+ }
+
+ method path_to_file (@file) { $self->root_path->file(@file) }
+
+ method path_to_dir (@dir) { $self->root_path->subdir(@dir) }
+}
82 lib/ReactionX/Jumpstart/LayoutSet.pm
@@ -0,0 +1,82 @@
+use MooseX::Declare;
+
+class ReactionX::Jumpstart::LayoutSet
+ with ReactionX::Jumpstart::Generating
+ with ReactionX::Jumpstart::Stashing
+ with ReactionX::Jumpstart::SubBuilding
+ with ReactionX::Jumpstart::Namespacing {
+
+ use MooseX::Types::Moose qw( Str Bool );
+
+ use Reaction::UI::View;
+
+
+ has layout_set_name => (
+ traits => [qw( ReactionX::Jumpstart::Meta::Attribute::Trait::Prompted )],
+ is => 'rw',
+ isa => Str,
+ question => 'Name of the LayoutSet?',
+ );
+
+ has layout_set_is_extension => (
+ traits => [qw( ReactionX::Jumpstart::Meta::Attribute::Trait::Prompted )],
+ is => 'rw',
+ isa => Bool,
+ question => "Is this LayoutSet an extension of another one?",
+ defaults_to => 0,
+ );
+
+ has base_layout_set_name => (
+ traits => [qw( ReactionX::Jumpstart::Meta::Attribute::Trait::Prompted )],
+ is => 'rw',
+ isa => Str,
+ question => "Name of the parent LayoutSet?",
+ );
+
+ has widget_name_is_explicit => (
+ traits => [qw( ReactionX::Jumpstart::Meta::Attribute::Trait::Prompted )],
+ is => 'rw',
+ isa => Bool,
+ question => "Does the LayoutSet require an explicit Widget?",
+ defaults_to => 0,
+ );
+
+ has widget_name => (
+ traits => [qw( ReactionX::Jumpstart::Meta::Attribute::Trait::Prompted )],
+ is => 'rw',
+ isa => Str,
+ question => "Name of the LayoutSet's explicit Widget?",
+ defaults_to => sub {
+ my ($self) = @_;
+
+ my $widget = join('', map { ucfirst($_) } split('_', $self->layout_set_name));
+ $widget = join('::', map { ucfirst($_) } split('/', $widget));
+
+ return $widget;
+ },
+ );
+
+
+ method JUMPSTART {
+
+ my $lset = $self->layout_set_name;
+ my $lset_file = $self->path_to_file('share/skin', $self->stash->{skin_name}, 'layout', "$lset.tt");
+
+ my %args = (layout_set => $lset);
+
+ if ($self->layout_set_is_extension) {
+ $args{layout_set_base} = $self->base_layout_set_name;
+ }
+
+ if ($self->widget_name_is_explicit) {
+ $args{widget_name} = $self->widget_name;
+ }
+
+ $self->build_file(
+ file => $lset_file,
+ dist => 'ReactionX-Jumpstart',
+ template => 'layout_set',
+ vars => \%args,
+ );
+ }
+}
122 lib/ReactionX/Jumpstart/Meta/Attribute/Trait/Prompted.pm
@@ -0,0 +1,122 @@
+use MooseX::Declare;
+
+role ReactionX::Jumpstart::Meta::Attribute::Trait::Prompted {
+
+ use Carp qw( croak );
+ use Term::Prompt;
+
+
+ has question => (
+ is => 'rw',
+ required => 1,
+ predicate => 'has_question',
+ );
+
+ has defaults_to => (
+ is => 'rw',
+ required => 0,
+ predicate => 'has_defaults_to',
+ );
+
+ has help_info => (
+ is => 'rw',
+ required => 0,
+ predicate => 'has_help_info',
+ );
+
+
+ around is_lazy { 1 }
+
+ around has_default { 1 }
+
+ around is_default_a_coderef { 1 }
+
+ around default ($instance) { $self->prompt_for_value($instance) }
+
+ around legal_options_for_inheritance { $self->$orig, qw( help_info defaults_to question ) }
+
+
+ method _build_value_from_spec (Object $instance, Str $option, $default?) {
+
+ return ''
+ unless $self->${\"has_$option"};
+
+ my $value = $self->$option;
+
+ return $value
+ unless ref $value;
+
+ return $instance->$value($default)
+ if ref $value eq 'CODE';
+
+ return $instance->${\($value->[0])}($default, @{ $value }[1 .. $#$value])
+ if ref $value eq 'ARRAY';
+
+ croak "No idea what to do with $value $option specification for ${\ $self->name} on ${\ref $self}";
+ }
+
+ method build_question ($instance, $default) { $self->_build_value_from_spec($instance, 'question', $default) }
+
+ method build_default_value ($instance) { $self->_build_value_from_spec($instance, 'defaults_to') }
+
+ method build_help_info ($instance, $default) { $self->_build_value_from_spec($instance, 'help_info', $default) }
+
+ method prompt_for_value ($instance) {
+
+ if (my $builder = $instance->can('_build_' . $self->name)) {
+ return $instance->$builder;
+ }
+
+ my $tc = $self->type_constraint
+ or croak "Attribute ${\($self->name)} can't be prompted without a type constraint";
+
+ my $try = $tc;
+ my @tries;
+
+ while ($try) {
+ push @tries, ( my $name = $try->name );
+
+ if (my $method = $self->can("prompt_for_${name}_value")) {
+
+ local $Term::Prompt::MULTILINE_INDENT = ' ';
+
+ VALUE:
+ while (1) {
+
+ my $result = $self->$method($instance, $tc, $self->build_default_value($instance));
+
+ if ($self->is_required and $result eq '') {
+ print "Value is required\n";
+ next VALUE;
+ }
+
+ return $result
+ if $tc->check($result);
+
+ printf "Invalid Input: %s\n", $tc->validate($result);
+ }
+ }
+
+ $try = $try->parent;
+ }
+
+ croak "Unable to locate 'prompt_for_*_value' method for ${\ $self->name} on ${\ref $self}. Tried as *: "
+ . join ', ', @tries;
+ }
+
+ method prompt_for_Str_value ($instance, $tc, $default) {
+ prompt('x',
+ $self->build_question($instance, $default),
+ $self->build_help_info($instance, $default),
+ $default,
+ );
+ }
+
+ method prompt_for_Bool_value ($instance, $tc, $default) {
+ prompt('y',
+ $self->build_question($instance, $default),
+ $self->build_help_info($instance, $default),
+ $default,
+ );
+ }
+}
24 lib/ReactionX/Jumpstart/Namespacing.pm
@@ -0,0 +1,24 @@
+use MooseX::Declare;
+
+role ReactionX::Jumpstart::Namespacing {
+
+ use MooseX::Types::Moose qw( Str Object );
+
+ has project_namespace => (
+ traits => [qw( ReactionX::Jumpstart::Meta::Attribute::Trait::Prompted )],
+ is => 'rw',
+ isa => Str,
+ required => 1,
+ question => 'Namespace of the project?',
+ help_info => 'example: MyApp',
+ );
+
+ has ui_namespace => (
+ traits => [qw( ReactionX::Jumpstart::Meta::Attribute::Trait::Prompted )],
+ is => 'rw',
+ isa => Str,
+ question => 'Name of the UI?',
+ defaults_to => 'Web',
+ help_info => sub { sprintf 'example: %s for %s::%s', $_[1], $_[0]->project_namespace, $_[1] },
+ );
+}
18 lib/ReactionX/Jumpstart/Stashing.pm
@@ -0,0 +1,18 @@
+use MooseX::Declare;
+
+role ReactionX::Jumpstart::Stashing {
+
+ use MooseX::Types::Moose qw( HashRef );
+
+
+ my $singleton_stash = {};
+
+ has stash => (is => 'ro', isa => HashRef, required => 1, default => sub { $singleton_stash });
+
+
+ method set_stash (%pairs) {
+
+ $self->stash->{ $_ } = $pairs{ $_ }
+ for keys %pairs;
+ }
+}
17 lib/ReactionX/Jumpstart/SubBuilding.pm
@@ -0,0 +1,17 @@
+use MooseX::Declare;
+
+role ReactionX::Jumpstart::SubBuilding {
+
+ use List::MoreUtils qw( uniq );
+
+ method new_sub_builder (Str $class, ArrayRef[Str] :$passthrough = [], HashRef :$additional = {}) {
+ return $class->new(
+ ( map { ($_ => $self->$_) }
+ grep { $self->can($_) }
+ uniq @$passthrough,
+ qw( root_path ui_namespace project_namespace stash ),
+ ),
+ %$additional,
+ );
+ }
+}
100 lib/ReactionX/Jumpstart/View.pm
@@ -0,0 +1,100 @@
+use MooseX::Declare;
+
+class ReactionX::Jumpstart::View
+ with ReactionX::Jumpstart::Generating
+ with ReactionX::Jumpstart::Stashing
+ with ReactionX::Jumpstart::SubBuilding
+ with ReactionX::Jumpstart::Namespacing {
+
+ use MooseX::Types::Moose qw( Str );
+
+
+ has view_namespace => (
+ traits => [qw( ReactionX::Jumpstart::Meta::Attribute::Trait::Prompted )],
+ is => 'rw',
+ isa => Str,
+ question => 'Name of the View?',
+ defaults_to => 'Site',
+ help_info => sub {
+ sprintf 'example: %s for %s::%s::View::%s',
+ $_[1],
+ $_[0]->project_namespace,
+ $_[0]->ui_namespace,
+ $_[1],
+ },
+ );
+
+ has skin_name => (
+ traits => [qw( ReactionX::Jumpstart::Meta::Attribute::Trait::Prompted )],
+ is => 'rw',
+ isa => Str,
+ question => "Name of your application's Skin?",
+ defaults_to => sub {
+
+ my $skin = lc join '::', $_[0]->project_namespace, $_[0]->ui_namespace;
+ $skin =~ s{::}{_}g;
+
+ return $skin;
+ },
+ );
+
+ has base_skin_name => (
+ traits => [qw( ReactionX::Jumpstart::Meta::Attribute::Trait::Prompted )],
+ is => 'rw',
+ isa => Str,
+ question => "Name of the Skin from which your Skin inherits?",
+ defaults_to => '/Reaction/default',
+ );
+
+
+ method JUMPSTART {
+
+ $self->jumpstart_view;
+ $self->jumpstart_skin;
+ }
+
+ method jumpstart_skin {
+
+ my $name = $self->skin_name;
+ my $base = $self->base_skin_name;
+
+ $self->set_stash(skin_name => $name);
+
+ my $layout_path = $self->mkpath('share/skin', $name, 'layout');
+ my $web_path = $self->mkpath('share/skin', $name, 'web');
+
+ $self->build_file(
+ file => $self->path_to_file('share/skin', $name, 'skin.conf'),
+ template => 'skin.conf',
+ dist => 'ReactionX-Jumpstart',
+ vars => {
+ base_skin_name => $base,
+ },
+ );
+ }
+
+ method jumpstart_view {
+
+ my $namespace = $self->stash->{site_view_name}
+ = $self->view_namespace;
+
+ my $package = $self->stash->{site_view_class}
+ = join '::',
+ $self->project_namespace,
+ $self->ui_namespace,
+ 'View',
+ $namespace;
+
+ $self->build_package(
+ package => $package,
+ dist => 'ReactionX-Jumpstart',
+ template => 'view',
+ );
+
+ $self->build_file(
+ file => $self->path_to_file('share/skin/defaults.conf'),
+ dist => 'ReactionX-Jumpstart',
+ template => 'defaults.conf',
+ );
+ }
+}
120 lib/ReactionX/Jumpstart/ViewGroup.pm
@@ -0,0 +1,120 @@
+use MooseX::Declare;
+
+class ReactionX::Jumpstart::ViewGroup
+ with ReactionX::Jumpstart::Generating
+ with ReactionX::Jumpstart::Stashing
+ with ReactionX::Jumpstart::SubBuilding
+ with ReactionX::Jumpstart::Namespacing {
+
+
+ use MooseX::Types::Moose qw( Str Object HashRef );
+ use Reaction::UI::View;
+
+ use aliased 'ReactionX::Jumpstart::ViewPort';
+ use aliased 'ReactionX::Jumpstart::Widget';
+ use aliased 'ReactionX::Jumpstart::LayoutSet';
+
+
+ has view_group_name => (
+ traits => [qw( ReactionX::Jumpstart::Meta::Attribute::Trait::Prompted )],
+ is => 'rw',
+ isa => Str,
+ question => 'Name of the group?',
+ help_info => sub {
+ my ($self, $default) = @_;
+
+ $default ||= 'Foo';
+
+ sprintf '%s for ViewPort::%s, Widget::%s, layout/%s.tt',
+ ($default) x 3,
+ Reaction::UI::View->layout_set_name_from_viewport("DUMMY::ViewPort::$default"),
+ },
+ );
+
+ has viewport_builder => (
+ isa => Object,
+ required => 1,
+ lazy_build => 1,
+ handles => { build_viewport => 'JUMPSTART' },
+ );
+
+ has viewport_builder_args => (
+ is => 'rw',
+ isa => HashRef,
+ required => 1,
+ default => sub { {} },
+ );
+
+ has widget_builder => (
+ isa => Object,
+ required => 1,
+ lazy_build => 1,
+ handles => { build_widget => 'JUMPSTART' },
+ );
+
+ has widget_builder_args => (
+ is => 'rw',
+ isa => HashRef,
+ required => 1,
+ default => sub { {} },
+ );
+
+ has layout_set_builder => (
+ isa => Object,
+ required => 1,
+ lazy_build => 1,
+ handles => { build_layout_set => 'JUMPSTART' },
+ );
+
+ has layout_set_builder_args => (
+ is => 'rw',
+ isa => HashRef,
+ required => 1,
+ default => sub { {} },
+ );
+
+
+ method JUMPSTART {
+
+ $self->build_viewport;
+ $self->build_widget;
+ $self->build_layout_set;
+ }
+
+ method _build_viewport_builder {
+
+ my $name = $self->view_group_name;
+
+ return $self->new_sub_builder(ViewPort,
+ additional => {
+ viewport_namespace => $name,
+ %{ $self->viewport_builder_args },
+ },
+ );
+ }
+
+ method _build_widget_builder {
+
+ my $name = $self->view_group_name;
+
+ return $self->new_sub_builder(Widget,
+ additional => {
+ widget_namespace => $name,
+ %{ $self->widget_builder_args },
+ },
+ );
+ }
+
+ method _build_layout_set_builder {
+
+ my $name = $self->view_group_name;
+
+ return $self->new_sub_builder(LayoutSet,
+ additional => {
+ layout_set_name => Reaction::UI::View->layout_set_name_from_viewport("DUMMY::ViewPort::$name"),
+ widget_name => $name,
+ %{ $self->layout_set_builder_args },
+ },
+ );
+ }
+}
55 lib/ReactionX/Jumpstart/ViewPort.pm
@@ -0,0 +1,55 @@
+use MooseX::Declare;
+
+class ReactionX::Jumpstart::ViewPort
+ with ReactionX::Jumpstart::Generating
+ with ReactionX::Jumpstart::Stashing
+ with ReactionX::Jumpstart::SubBuilding
+ with ReactionX::Jumpstart::Namespacing {
+
+ use MooseX::Types::Moose qw( Str );
+
+
+ has viewport_namespace => (
+ traits => [qw( ReactionX::Jumpstart::Meta::Attribute::Trait::Prompted )],
+ is => 'rw',
+ isa => Str,
+ question => 'Name of the ViewPort?',
+ help_info => sub {
+ sprintf '%s for %s::%s::ViewPort::%s',
+ $_[1] || 'Foo',
+ $_[0]->project_namespace,
+ $_[0]->ui_namespace,
+ $_[1] || 'Foo',
+ },
+ );
+
+ has viewport_base_class => (
+ traits => [qw( ReactionX::Jumpstart::Meta::Attribute::Trait::Prompted )],
+ is => 'rw',
+ isa => Str,
+ question => "ClassName of the ViewPort's parent?",
+ defaults_to => 'Reaction::UI::ViewPort',
+ );
+
+
+ method JUMPSTART {
+
+ my $package = join '::',
+ $self->project_namespace,
+ $self->ui_namespace,
+ 'ViewPort',
+ $self->viewport_namespace;
+
+ my $parent = $self->viewport_base_class;
+
+ $self->build_package(
+ package => $package,
+ dist => 'ReactionX-Jumpstart',
+ template => 'viewport',
+ vars => {
+ viewport_package => $package,
+ viewport_base => $parent,
+ },
+ );
+ }
+}
53 lib/ReactionX/Jumpstart/Widget.pm
@@ -0,0 +1,53 @@
+use MooseX::Declare;
+
+class ReactionX::Jumpstart::Widget
+ with ReactionX::Jumpstart::Generating
+ with ReactionX::Jumpstart::Stashing
+ with ReactionX::Jumpstart::SubBuilding
+ with ReactionX::Jumpstart::Namespacing {
+
+ use MooseX::Types::Moose qw( Str );
+
+
+ has widget_namespace => (
+ traits => [qw( ReactionX::Jumpstart::Meta::Attribute::Trait::Prompted )],
+ is => 'rw',
+ isa => Str,
+ question => 'Name of the Widget?',
+ help_info => sub {
+ sprintf '%s for %s::Widget::%s',
+ $_[1] || 'Foo',
+ $_[0]->stash->{site_view_class},
+ $_[1] || 'Foo',
+ },
+ );
+
+ has widget_base_class => (
+ traits => [qw( ReactionX::Jumpstart::Meta::Attribute::Trait::Prompted )],
+ is => 'rw',
+ isa => Str,
+ question => "ClassName of the Widget's parent?",
+ defaults_to => 'Reaction::UI::Widget',
+ );
+
+
+ method JUMPSTART {
+
+ my $package = join '::',
+ $self->stash->{site_view_class},
+ 'Widget',
+ $self->widget_namespace;
+
+ my $parent = $self->widget_base_class;
+
+ $self->build_package(
+ package => $package,
+ dist => 'ReactionX-Jumpstart',
+ template => 'widget',
+ vars => {
+ widget_package => $package,
+ widget_base => $parent,
+ },
+ );
+ }
+}
11 script/reaction-jumpstart.pl
@@ -0,0 +1,11 @@
+#!/usr/bin/env perl
+use strict;
+use warnings;
+
+use Find::Lib '../lib';
+use Find::Lib '../fake_share';
+
+system 'rm -fr test';
+
+use ReactionX::Jumpstart;
+ReactionX::Jumpstart->new->JUMPSTART;
15 share/application.conf.tt
@@ -0,0 +1,15 @@
+name [% application_name %]
+
+<static>
+ include_path __path_to(share/skin/[% skin_name %]/web)__
+</static>
+
+<View [% site_view_name %]>
+ skin_name [% skin_name %]
+</View>
+
+[%- IF root_controller_namespace %]
+<Controller [% root_controller_namespace %]>
+ window_title [% application_name %]
+</Controller>
+[% END -%]
16 share/application.tt
@@ -0,0 +1,16 @@
+package [% application_package %];
+use strict;
+use warnings;
+
+use Catalyst::Runtime '[% catalyst_version %]';
+use Reaction '[% reaction_version %]';
+
+use Catalyst qw(
+ ConfigLoader
+ Static::Simple
+);
+
+__PACKAGE__->config(name => '[% application_name %]');
+__PACKAGE__->setup;
+
+1;
36 share/controller.tt
@@ -0,0 +1,36 @@
+package [% controller_package %];
+use strict;
+use warnings;
+use parent '[% controller_base %]';
+
+use Reaction::Class;
+
+[%- IF site_layout_is_pushed %]
+use aliased '[% site_layout_class %]' => 'SiteLayout';
+[% END -%]
+
+use namespace::autoclean;
+
+__PACKAGE__->config(
+[% controller_config | indent(4) %]
+);
+
+sub base: Chained('[% base_chained_to %]') PathPart('[% base_path_part %]') CaptureArgs(0) { }
+
+[%- IF site_layout_is_pushed %]
+sub site: Chained('base') PathPart('') CaptureArgs(0) {
+ my ($self, $ctx) = @_;
+
+ $self->push_viewport(SiteLayout,
+ static_base_uri => $ctx->uri_for('/static')->as_string,
+ title => $self->window_title,
+ meta_info => {
+ http_header => {
+ 'Content-Type' => 'text/html;charset=utf-8',
+ },
+ },
+ );
+}
+[% END -%]
+
+1;
2  share/defaults.conf.tt
@@ -0,0 +1,2 @@
+widget_search_path [% site_view_class %]::Widget
+widget_search_path Reaction::UI::Widget
11 share/layout_set.tt
@@ -0,0 +1,11 @@
+[%- IF widget_name; mark_end = 1 -%]
+=widget [% widget_name %]
+
+[% END -%]
+[%- IF layout_set_base; mark_end = 1 -%]
+=extends [% layout_set_base %]
+
+[% END -%]
+[%- IF mark_end -%]
+=cut
+[% END -%]
1  share/skin.conf.tt
@@ -0,0 +1 @@
+extends [% base_skin_name %]
10 share/view.tt
@@ -0,0 +1,10 @@
+package [% site_view_class %];
+use Reaction::Class;
+
+use namespace::autoclean;
+
+extends 'Reaction::UI::View::TT';
+
+__PACKAGE__->meta->make_immutable;
+
+1;
8 share/viewport.tt
@@ -0,0 +1,8 @@
+package [% viewport_package %];
+use Reaction::Class;
+
+use namespace::autoclean;
+
+extends '[% viewport_base %]';
+
+1;
10 share/widget.tt
@@ -0,0 +1,10 @@
+package [% widget_package %];
+use Reaction::UI::WidgetClass;
+
+use namespace::autoclean;
+
+[%- IF widget_base != 'Reaction::UI::Widget' %]
+extends '[% widget_base %]';
+[% END -%]
+
+1;
Please sign in to comment.
Something went wrong with that request. Please try again.