aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--componentui.conf4
-rw-r--r--lib/ComponentUI.pm2
-rw-r--r--lib/ComponentUI/Controller/Root.pm19
-rw-r--r--lib/ComponentUI/View/Site.pm36
-rw-r--r--lib/ComponentUI/View/Site/Widget/Index.pm11
-rw-r--r--lib/ComponentUI/View/Site/Widget/Layout.pm17
-rw-r--r--lib/Reaction/UI/LayoutSet.pm8
-rw-r--r--lib/Reaction/UI/LayoutSet/TT.pm3
-rw-r--r--lib/Reaction/UI/View.pm16
-rw-r--r--lib/Reaction/UI/ViewPort/ActionForm.pm67
-rw-r--r--lib/Reaction/UI/ViewPort/DisplayField/Boolean.pm2
-rw-r--r--lib/Reaction/UI/ViewPort/DisplayField/Collection.pm2
-rw-r--r--lib/Reaction/UI/ViewPort/DisplayField/DateTime.pm2
-rw-r--r--lib/Reaction/UI/ViewPort/DisplayField/List.pm2
-rw-r--r--lib/Reaction/UI/ViewPort/DisplayField/Number.pm2
-rw-r--r--lib/Reaction/UI/ViewPort/DisplayField/RelatedObject.pm2
-rw-r--r--lib/Reaction/UI/ViewPort/DisplayField/String.pm2
-rw-r--r--lib/Reaction/UI/ViewPort/DisplayField/Text.pm2
-rw-r--r--lib/Reaction/UI/ViewPort/Field.pm4
-rw-r--r--lib/Reaction/UI/ViewPort/Field/Boolean.pm4
-rw-r--r--lib/Reaction/UI/ViewPort/Field/ChooseMany.pm2
-rw-r--r--lib/Reaction/UI/ViewPort/Field/ChooseOne.pm2
-rw-r--r--lib/Reaction/UI/ViewPort/Field/DateTime.pm18
-rw-r--r--lib/Reaction/UI/ViewPort/Field/File.pm6
-rw-r--r--lib/Reaction/UI/ViewPort/Field/Number.pm4
-rw-r--r--lib/Reaction/UI/ViewPort/Field/Password.pm4
-rw-r--r--lib/Reaction/UI/ViewPort/Field/String.pm6
-rw-r--r--lib/Reaction/UI/ViewPort/Field/Text.pm4
-rw-r--r--lib/Reaction/UI/ViewPort/Field/TimeRange.pm30
-rw-r--r--lib/Reaction/UI/ViewPort/ObjectView.pm8
-rw-r--r--lib/Reaction/UI/ViewPort/TimeRangeCollection.pm92
-rw-r--r--lib/Reaction/UI/Widget/ActionForm.pm7
-rw-r--r--lib/Reaction/UI/Widget/DisplayField.pm4
-rw-r--r--lib/Reaction/UI/Widget/Field.pm2
-rw-r--r--lib/Reaction/UI/Widget/Field/Boolean.pm2
-rw-r--r--lib/Reaction/UI/Widget/Field/ChooseMany.pm2
-rw-r--r--lib/Reaction/UI/Widget/Field/ChooseOne.pm1
-rw-r--r--lib/Reaction/UI/Widget/Field/DateTime.pm1
-rw-r--r--lib/Reaction/UI/Widget/Field/File.pm1
-rw-r--r--lib/Reaction/UI/Widget/Field/HiddenArray.pm1
-rw-r--r--lib/Reaction/UI/Widget/Field/Number.pm1
-rw-r--r--lib/Reaction/UI/Widget/Field/Password.pm1
-rw-r--r--lib/Reaction/UI/Widget/Field/String.pm2
-rw-r--r--lib/Reaction/UI/Widget/Field/Text.pm1
-rw-r--r--lib/Reaction/UI/Widget/Field/TimeRange.pm1
-rw-r--r--lib/Reaction/UI/Widget/ListView.pm14
-rw-r--r--lib/Reaction/UI/Widget/ObjectView.pm5
-rw-r--r--share/skin/default/layout/action_form4
-rw-r--r--share/skin/default/layout/display_field/boolean4
-rw-r--r--share/skin/default/layout/display_field/collection6
-rw-r--r--share/skin/default/layout/display_field/date_time4
-rw-r--r--share/skin/default/layout/display_field/list6
-rw-r--r--share/skin/default/layout/display_field/number4
-rw-r--r--share/skin/default/layout/display_field/related_object4
-rw-r--r--share/skin/default/layout/display_field/string4
-rw-r--r--share/skin/default/layout/display_field/text4
-rw-r--r--share/skin/default/layout/field/boolean12
-rw-r--r--share/skin/default/layout/field/choose_many14
-rw-r--r--share/skin/default/layout/field/choose_one12
-rw-r--r--share/skin/default/layout/field/date_time12
-rw-r--r--share/skin/default/layout/field/file12
-rw-r--r--share/skin/default/layout/field/number14
-rw-r--r--share/skin/default/layout/field/password14
-rw-r--r--share/skin/default/layout/field/string12
-rw-r--r--share/skin/default/layout/field/text12
-rw-r--r--share/skin/default/layout/field/time_range12
-rw-r--r--share/skin/default/layout/index5
-rw-r--r--share/skin/default/layout/layout56
-rw-r--r--share/skin/default/layout/object_view8
-rw-r--r--share/skin/default/web/componentui-basic.css146
70 files changed, 581 insertions, 229 deletions
diff --git a/componentui.conf b/componentui.conf
index 2d43094..9a0ed59 100644
--- a/componentui.conf
+++ b/componentui.conf
@@ -9,3 +9,7 @@ using_frontend_proxy 1
</ViewPort>
</Action>
</Controller>
+
+<View Site>
+ skin_name default
+</View> \ No newline at end of file
diff --git a/lib/ComponentUI.pm b/lib/ComponentUI.pm
index f1938c5..ae7751f 100644
--- a/lib/ComponentUI.pm
+++ b/lib/ComponentUI.pm
@@ -13,7 +13,7 @@ use Catalyst::Runtime '5.70';
# Static::Simple: will serve static files from the application's root
# directory
-use Catalyst qw/-Debug ConfigLoader Static::Simple I18N/;
+use Catalyst qw/ ConfigLoader -Debug Static::Simple I18N /;
our $VERSION = '0.01';
diff --git a/lib/ComponentUI/Controller/Root.pm b/lib/ComponentUI/Controller/Root.pm
index 1d7bd58..567cf3b 100644
--- a/lib/ComponentUI/Controller/Root.pm
+++ b/lib/ComponentUI/Controller/Root.pm
@@ -12,15 +12,14 @@ use aliased 'Reaction::UI::ViewPort';
# so they function identically to actions created in MyApp.pm
#
__PACKAGE__->config(
- view_name => 'XHTML',
+ view_name => 'Site',
window_title => 'Reaction Test App',
- content_type => 'text/html',
- namespace => '',
+ namespace => ''
);
sub base :Chained('/') :PathPart('') :CaptureArgs(0) {
my ($self, $c) = @_;
- $self->push_viewport(ViewPort, layout => 'xhtml');
+ $self->push_viewport(ViewPort, layout => 'layout');
}
sub root :Chained('base') :PathPart('') :Args(0) {
@@ -28,4 +27,16 @@ sub root :Chained('base') :PathPart('') :Args(0) {
$self->push_viewport(ViewPort, layout => 'index');
}
+sub static :Chained('base') :PathPart('static') :Args {
+ my ($self, $c, @args) = @_;
+ return if $c->stash->{window}->view->serve_static_file($c, \@args);
+ $c->forward('error_404');
+}
+
+sub error_404 :Private {
+ my ($self, $c) = @_;
+ $c->res->body("Error 404");
+ $c->res->status(404);
+}
+
1;
diff --git a/lib/ComponentUI/View/Site.pm b/lib/ComponentUI/View/Site.pm
new file mode 100644
index 0000000..cbb2d28
--- /dev/null
+++ b/lib/ComponentUI/View/Site.pm
@@ -0,0 +1,36 @@
+package ComponentUI::View::Site;
+
+use Reaction::Class;
+use aliased 'Reaction::UI::View::TT';
+
+class Site is TT, which {
+
+};
+
+
+use Class::MOP;
+
+{
+ my @reflect_widgets = qw(ActionForm ObjectView ListView
+ Field::File
+ Field::Password
+ Field::Text DisplayField::Text
+ Field::Number DisplayField::Number
+ Field::String DisplayField::String
+ Field::Boolean DisplayField::Boolean
+ Field::DateTime DisplayField::DateTime
+ Field::ChooseOne DisplayField::RelatedObject
+ Field::ChooseMany DisplayField::Collection
+ Field::HiddenArray DisplayField::List
+ );
+
+
+ for (@reflect_widgets){
+ my $base = "Reaction::UI::Widget::${_}";
+ my $target = "ComponentUI::View::Site::Widget::${_}";
+ Class::MOP::load_class( $base );
+ $base->meta->create($target, superclasses => [$base]);
+ }
+}
+
+1;
diff --git a/lib/ComponentUI/View/Site/Widget/Index.pm b/lib/ComponentUI/View/Site/Widget/Index.pm
new file mode 100644
index 0000000..21175ae
--- /dev/null
+++ b/lib/ComponentUI/View/Site/Widget/Index.pm
@@ -0,0 +1,11 @@
+package ComponentUI::View::Site::Widget::Index;
+
+use Reaction::UI::WidgetClass;
+
+class Index which {
+
+ widget renders [ string {"DUMMY"} ];
+
+};
+
+1;
diff --git a/lib/ComponentUI/View/Site/Widget/Layout.pm b/lib/ComponentUI/View/Site/Widget/Layout.pm
new file mode 100644
index 0000000..380a03a
--- /dev/null
+++ b/lib/ComponentUI/View/Site/Widget/Layout.pm
@@ -0,0 +1,17 @@
+package ComponentUI::View::Site::Widget::Layout;
+
+use Reaction::UI::WidgetClass;
+
+class Layout which {
+
+ widget renders [ qw(menu sidebar header main_content) =>
+ { viewport => func('self', 'viewport') } ];
+
+ menu renders [ string { "DUMMY" } ];
+ sidebar renders [ string { "Sidebar Shit" } ];
+ header renders [ string { "DUMMY" } ];
+ main_content renders [ viewport over func('viewport', 'inner')];
+
+};
+
+1;
diff --git a/lib/Reaction/UI/LayoutSet.pm b/lib/Reaction/UI/LayoutSet.pm
index 60d68d9..1cdb0e9 100644
--- a/lib/Reaction/UI/LayoutSet.pm
+++ b/lib/Reaction/UI/LayoutSet.pm
@@ -18,6 +18,7 @@ class LayoutSet which {
my $found;
SEARCH: foreach my $path (@path) {
my $cand = $path->file($self->name);
+ print STDERR $cand,"\n";
if ($cand->stat) {
$self->_load_file($cand);
$found = 1;
@@ -44,7 +45,12 @@ class LayoutSet which {
implements 'widget_type' => as {
my ($self) = @_;
- return join('', map { ucfirst($_) } split('_', $self->name));
+ my $widget = join('', map { ucfirst($_) } split('_', $self->name));
+ $widget = join('::', map { ucfirst($_) } split('/', $widget));
+
+ print STDERR "--- ", $self->name, " maps to widget $widget \n";
+
+ return $widget;
};
};
diff --git a/lib/Reaction/UI/LayoutSet/TT.pm b/lib/Reaction/UI/LayoutSet/TT.pm
index 72d3fad..02b3cde 100644
--- a/lib/Reaction/UI/LayoutSet/TT.pm
+++ b/lib/Reaction/UI/LayoutSet/TT.pm
@@ -23,6 +23,7 @@ class TT is LayoutSet, which {
|| confess "tt_object not provided to new()";
my $tt_args = { data => {} };
my $name = $self->name;
+ $name =~ s/\//__/g; #slashes are not happy here...
my $fragments = $self->fragments;
my $tt_source = qq{[% VIEW ${name};\n\n}.
join("\n\n",
@@ -39,6 +40,6 @@ class TT is LayoutSet, which {
return $tt_args->{data}{view};
};
-};
+};
1;
diff --git a/lib/Reaction/UI/View.pm b/lib/Reaction/UI/View.pm
index aa30878..987909c 100644
--- a/lib/Reaction/UI/View.pm
+++ b/lib/Reaction/UI/View.pm
@@ -59,19 +59,23 @@ class View which {
my $base = $self->blessed;
my $tail = $layout_set->widget_type;
my $class = join('::', $base, 'Widget', $tail);
- Class::MOP::load_class($class);
+ eval { Class::MOP::load_class($class) };
+ confess "Couldn't load widget '$class': $@" if $@;
return $class;
};
implements 'layout_set_for' => as {
my ($self, $vp) = @_;
+ print STDERR "Getting layoutset for VP ".(ref($vp) || "SC:".$vp)."\n";
my $lset_name = eval { $vp->layout };
confess "Couldn't call layout method on \$vp arg ${vp}: $@" if $@;
unless (length($lset_name)) {
- my $last = (split('::', ref($vp)))[-1];
- #previously: join("_", map { lc($_) } split(/(?=[A-Z])/, $last))
- $last =~ s/([a-z0-9])([A-Z])/${1}_${2}/g
- $lset_name = lc($last);
+ my $vp_class = ref($vp) || $vp;
+ my ($last) = ($vp_class =~ /.*(?:::ViewPort::)(.+?)$/);
+ my @fragments = split('::', $last);
+ $_ = join("_", split(/(?=[A-Z])/, $_)) for @fragments;
+ $lset_name = lc(join('/', @fragments));
+ print STDERR "--- $vp_class is rendered as $lset_name\n";
}
my $cache = $self->_layout_set_cache;
return $cache->{$lset_name} ||= $self->create_layout_set($lset_name);
@@ -86,7 +90,7 @@ class View which {
implements 'find_related_class' => as {
my ($self, $rel) = @_;
- my $own_class = ref($self)||$self;
+ my $own_class = ref($self) || $self;
confess View." is abstract, you must subclass it" if $own_class eq View;
foreach my $super ($own_class->meta->class_precedence_list) {
next if $super eq View;
diff --git a/lib/Reaction/UI/ViewPort/ActionForm.pm b/lib/Reaction/UI/ViewPort/ActionForm.pm
index bb97bf3..b28c25d 100644
--- a/lib/Reaction/UI/ViewPort/ActionForm.pm
+++ b/lib/Reaction/UI/ViewPort/ActionForm.pm
@@ -16,45 +16,45 @@ use aliased 'Reaction::UI::ViewPort::Field::TimeRange';
class ActionForm is 'Reaction::UI::ViewPort', which {
has action => (
- isa => 'Reaction::InterfaceModel::Action', is => 'ro', required => 1
- );
+ isa => 'Reaction::InterfaceModel::Action', is => 'ro', required => 1
+ );
has ordered_fields => (is => 'rw', isa => 'ArrayRef', lazy_build => 1);
has _field_map => (
- isa => 'HashRef', is => 'rw', init_arg => 'fields', lazy_build => 1,
- );
+ isa => 'HashRef', is => 'rw', init_arg => 'fields', lazy_build => 1,
+ );
has changed => (
- isa => 'Int', is => 'rw', reader => 'is_changed', default => sub { 0 }
- );
+ isa => 'Int', is => 'rw', reader => 'is_changed', default => sub { 0 }
+ );
has next_action => (
- isa => 'ArrayRef', is => 'rw', required => 0, predicate => 'has_next_action'
- );
+ isa => 'ArrayRef', is => 'rw', required => 0, predicate => 'has_next_action'
+ );
has on_apply_callback => (
- isa => 'CodeRef', is => 'rw', required => 0,
- predicate => 'has_on_apply_callback'
- );
+ isa => 'CodeRef', is => 'rw', required => 0,
+ predicate => 'has_on_apply_callback'
+ );
has ok_label => (
- isa => 'Str', is => 'rw', required => 1, default => sub { 'ok' }
- );
+ isa => 'Str', is => 'rw', required => 1, default => sub { 'ok' }
+ );
has apply_label => (
- isa => 'Str', is => 'rw', required => 1, default => sub { 'apply' }
- );
+ isa => 'Str', is => 'rw', required => 1, default => sub { 'apply' }
+ );
has close_label => (isa => 'Str', is => 'rw', lazy_fail => 1);
has close_label_close => (
- isa => 'Str', is => 'rw', required => 1, default => sub { 'close' }
- );
+ isa => 'Str', is => 'rw', required => 1, default => sub { 'close' }
+ );
has close_label_cancel => (
- isa => 'Str', is => 'rw', required => 1, default => sub { 'cancel' }
- );
+ isa => 'Str', is => 'rw', required => 1, default => sub { 'cancel' }
+ );
sub fields { shift->_field_map }
@@ -83,7 +83,7 @@ class ActionForm is 'Reaction::UI::ViewPort', which {
my $constraint = $attr->type_constraint;
my $base_name = $constraint->name;
my $tried_isa = 0;
- CONSTRAINT: while (defined($constraint)) {
+ CONSTRAINT: while (defined($constraint)) {
my $name = $constraint->name;
if (eval { $name->can('meta') } && !$tried_isa++) {
foreach my $class ($name->meta->class_precedence_list) {
@@ -125,16 +125,17 @@ class ActionForm is 'Reaction::UI::ViewPort', which {
implements build_ordered_fields => as {
my $self = shift;
- $self->sort_by_spec($self->column_order, [keys %{$self->_field_map_}])};
+ my $ordered = $self->sort_by_spec($self->column_order, [keys %{$self->_field_map}]);
+ return [@{$self->_field_map}{@$ordered}];
};
implements can_apply => as {
my ($self) = @_;
- foreach my $field (values %{$self->_field_map}) {
+ foreach my $field ( @{ $self->ordered_fields } ) {
return 0 if $field->needs_sync;
- # if e.g. a datetime field has an invalid value that can't be re-assembled
- # into a datetime object, the action may be in a consistent state but
- # not synchronized from the fields; in this case, we must not apply
+ # if e.g. a datetime field has an invalid value that can't be re-assembled
+ # into a datetime object, the action may be in a consistent state but
+ # not synchronized from the fields; in this case, we must not apply
}
return $self->action->can_apply;
};
@@ -212,13 +213,13 @@ class ActionForm is 'Reaction::UI::ViewPort', which {
%extra = %$config;
}
my $field = $class->new(
- action => $self->action,
- attribute => $attr,
- name => $attr->name,
- location => join('-', $self->location, 'field', $attr->name),
- ctx => $self->ctx,
- %extra
- );
+ action => $self->action,
+ attribute => $attr,
+ name => $attr->name,
+ location => join('-', $self->location, 'field', $attr->name),
+ ctx => $self->ctx,
+ %extra
+ );
return ($attr_name => $field);
};
@@ -297,7 +298,7 @@ class ActionForm is 'Reaction::UI::ViewPort', which {
};
-1;
+ 1;
=head1 NAME
diff --git a/lib/Reaction/UI/ViewPort/DisplayField/Boolean.pm b/lib/Reaction/UI/ViewPort/DisplayField/Boolean.pm
index 9389436..1502fe6 100644
--- a/lib/Reaction/UI/ViewPort/DisplayField/Boolean.pm
+++ b/lib/Reaction/UI/ViewPort/DisplayField/Boolean.pm
@@ -5,7 +5,7 @@ use aliased 'Reaction::UI::ViewPort::DisplayField';
class Boolean, is DisplayField, which {
has '+value' => (isa => 'Bool');
- has '+layout' => (default => 'displayfield/value_string');
+ #has '+layout' => (default => 'displayfield/value_string');
has value_string => (isa => 'Str', is => 'rw', lazy_build => 1);
diff --git a/lib/Reaction/UI/ViewPort/DisplayField/Collection.pm b/lib/Reaction/UI/ViewPort/DisplayField/Collection.pm
index f4cec97..02383cf 100644
--- a/lib/Reaction/UI/ViewPort/DisplayField/Collection.pm
+++ b/lib/Reaction/UI/ViewPort/DisplayField/Collection.pm
@@ -5,7 +5,7 @@ use Scalar::Util 'blessed';
class Collection is 'Reaction::UI::ViewPort::DisplayField', which {
has '+value' => (isa => 'ArrayRef');
- has '+layout' => (default => 'displayfield/list');
+ #has '+layout' => (default => 'displayfield/list');
has value_names => (isa => 'ArrayRef', is => 'ro', lazy_build => 1);
diff --git a/lib/Reaction/UI/ViewPort/DisplayField/DateTime.pm b/lib/Reaction/UI/ViewPort/DisplayField/DateTime.pm
index 92d5b81..b8e8d89 100644
--- a/lib/Reaction/UI/ViewPort/DisplayField/DateTime.pm
+++ b/lib/Reaction/UI/ViewPort/DisplayField/DateTime.pm
@@ -6,7 +6,7 @@ use aliased 'Reaction::UI::ViewPort::DisplayField';
class DateTime is DisplayField, which {
has '+value' => (isa => 'DateTime');
- has '+layout' => (default => 'displayfield/value_string');
+ #has '+layout' => (default => 'displayfield/value_string');
has value_string => (isa => 'Str', is => 'rw', lazy_build => 1);
diff --git a/lib/Reaction/UI/ViewPort/DisplayField/List.pm b/lib/Reaction/UI/ViewPort/DisplayField/List.pm
index d70f1ed..76fa250 100644
--- a/lib/Reaction/UI/ViewPort/DisplayField/List.pm
+++ b/lib/Reaction/UI/ViewPort/DisplayField/List.pm
@@ -6,7 +6,7 @@ use aliased 'Reaction::UI::ViewPort::DisplayField';
class List is DisplayField, which {
has '+value' => (isa => 'ArrayRef');
- has '+layout' => (default => 'displayfield/list');
+ #has '+layout' => (default => 'displayfield/list');
has value_names => (isa => 'ArrayRef', is => 'ro', lazy_build => 1);
diff --git a/lib/Reaction/UI/ViewPort/DisplayField/Number.pm b/lib/Reaction/UI/ViewPort/DisplayField/Number.pm
index 7c46d06..358154d 100644
--- a/lib/Reaction/UI/ViewPort/DisplayField/Number.pm
+++ b/lib/Reaction/UI/ViewPort/DisplayField/Number.pm
@@ -4,7 +4,7 @@ use Reaction::Class;
use aliased 'Reaction::UI::ViewPort::DisplayField';
class Number is DisplayField, which {
- has '+layout' => (default => 'displayfield/string');
+ #has '+layout' => (default => 'displayfield/string');
};
1;
diff --git a/lib/Reaction/UI/ViewPort/DisplayField/RelatedObject.pm b/lib/Reaction/UI/ViewPort/DisplayField/RelatedObject.pm
index 3cd217c..9700ac0 100644
--- a/lib/Reaction/UI/ViewPort/DisplayField/RelatedObject.pm
+++ b/lib/Reaction/UI/ViewPort/DisplayField/RelatedObject.pm
@@ -6,7 +6,7 @@ use aliased 'Reaction::UI::ViewPort::DisplayField';
class RelatedObject is DisplayField, which {
- has '+layout' => (default => 'displayfield/value_string');
+ #has '+layout' => (default => 'displayfield/value_string');
has value_string => (isa => 'Str', is => 'ro', lazy_build => 1);
diff --git a/lib/Reaction/UI/ViewPort/DisplayField/String.pm b/lib/Reaction/UI/ViewPort/DisplayField/String.pm
index 3aab498..530cd08 100644
--- a/lib/Reaction/UI/ViewPort/DisplayField/String.pm
+++ b/lib/Reaction/UI/ViewPort/DisplayField/String.pm
@@ -5,7 +5,7 @@ use aliased 'Reaction::UI::ViewPort::DisplayField';
class String is DisplayField, which {
has '+value' => (isa => 'Str');
- has '+layout' => (default => 'displayfield/string');
+ #has '+layout' => (default => 'displayfield/string');
};
1;
diff --git a/lib/Reaction/UI/ViewPort/DisplayField/Text.pm b/lib/Reaction/UI/ViewPort/DisplayField/Text.pm
index c9e2c27..ea68e8c 100644
--- a/lib/Reaction/UI/ViewPort/DisplayField/Text.pm
+++ b/lib/Reaction/UI/ViewPort/DisplayField/Text.pm
@@ -5,7 +5,7 @@ use aliased 'Reaction::UI::ViewPort::DisplayField';
class Text is DisplayField, which {
has '+value' => (isa => 'Str');
- has '+layout' => (default => 'displayfield/text');
+ #has '+layout' => (default => 'displayfield/text');
};
1;
diff --git a/lib/Reaction/UI/ViewPort/Field.pm b/lib/Reaction/UI/ViewPort/Field.pm
index 41a7c42..06d0598 100644
--- a/lib/Reaction/UI/ViewPort/Field.pm
+++ b/lib/Reaction/UI/ViewPort/Field.pm
@@ -42,7 +42,9 @@ class Field is 'Reaction::UI::ViewPort', which {
implements build_label => as {
my ($self) = @_;
- return join(' ', map { ucfirst } split('_', $self->name));
+ my $label = join(' ', map { ucfirst } split('_', $self->name));
+ print STDERR "Field " . $self->name . " has label '$label'\n";
+ return $label;
};
implements build_value => as {
diff --git a/lib/Reaction/UI/ViewPort/Field/Boolean.pm b/lib/Reaction/UI/ViewPort/Field/Boolean.pm
index 34f7aae..fb0d886 100644
--- a/lib/Reaction/UI/ViewPort/Field/Boolean.pm
+++ b/lib/Reaction/UI/ViewPort/Field/Boolean.pm
@@ -5,11 +5,11 @@ use Reaction::Class;
class Boolean is 'Reaction::UI::ViewPort::Field', which {
has '+value' => (isa => 'Bool');
- has '+layout' => (default => 'checkbox');
+ #has '+layout' => (default => 'checkbox');
};
-1;
+1;
=head1 NAME
diff --git a/lib/Reaction/UI/ViewPort/Field/ChooseMany.pm b/lib/Reaction/UI/ViewPort/Field/ChooseMany.pm
index 35f6710..9337a3c 100644
--- a/lib/Reaction/UI/ViewPort/Field/ChooseMany.pm
+++ b/lib/Reaction/UI/ViewPort/Field/ChooseMany.pm
@@ -4,7 +4,7 @@ use Reaction::Class;
class ChooseMany is 'Reaction::UI::ViewPort::Field::ChooseOne', which {
- has '+layout' => (default => 'dual_select_group');
+ #has '+layout' => (default => 'dual_select_group');
has '+value' => (isa => 'ArrayRef');
my $listify = sub { # quick utility function, $listify->($arg)
diff --git a/lib/Reaction/UI/ViewPort/Field/ChooseOne.pm b/lib/Reaction/UI/ViewPort/Field/ChooseOne.pm
index 0d44fd7..703a26f 100644
--- a/lib/Reaction/UI/ViewPort/Field/ChooseOne.pm
+++ b/lib/Reaction/UI/ViewPort/Field/ChooseOne.pm
@@ -6,7 +6,7 @@ use Scalar::Util 'blessed';
class ChooseOne is 'Reaction::UI::ViewPort::Field', which {
- has '+layout' => (default => 'select');
+ #has '+layout' => (default => 'select');
has valid_values => (isa => 'ArrayRef', is => 'ro', lazy_build => 1);
has value_choices => (isa => 'ArrayRef', is => 'ro', lazy_build => 1);
diff --git a/lib/Reaction/UI/ViewPort/Field/DateTime.pm b/lib/Reaction/UI/ViewPort/Field/DateTime.pm
index 2b8509f..6d2958f 100644
--- a/lib/Reaction/UI/ViewPort/Field/DateTime.pm
+++ b/lib/Reaction/UI/ViewPort/Field/DateTime.pm
@@ -7,18 +7,18 @@ use Time::ParseDate ();
class DateTime is 'Reaction::UI::ViewPort::Field', which {
has '+value' => (isa => 'DateTime');
-
- has '+layout' => (default => 'dt_textfield');
-
+
+ #has '+layout' => (default => 'dt_textfield');
+
has value_string => (
isa => 'Str', is => 'rw', lazy_build => 1,
trigger_adopt('value_string')
);
-
+
has value_string_default_format => (
isa => 'Str', is => 'rw', required => 1, default => sub { "%F %H:%M:%S" }
);
-
+
implements build_value_string => as {
my $self = shift;
@@ -29,11 +29,11 @@ class DateTime is 'Reaction::UI::ViewPort::Field', which {
#<mst> eval { $self->value } ... is probably the best solution atm
my $value = eval { $self->value };
return '' unless $self->has_value;
- my $format = $self->value_string_default_format;
+ my $format = $self->value_string_default_format;
return $value->strftime($format) if $value;
return '';
};
-
+
implements adopt_value_string => as {
my ($self) = @_;
my $value = $self->value_string;
@@ -47,14 +47,14 @@ class DateTime is 'Reaction::UI::ViewPort::Field', which {
$self->needs_sync(1);
}
};
-
+
override accept_events => sub {
('value_string', super());
};
};
-1;
+1;
=head1 NAME
diff --git a/lib/Reaction/UI/ViewPort/Field/File.pm b/lib/Reaction/UI/ViewPort/Field/File.pm
index 557826d..a1d181c 100644
--- a/lib/Reaction/UI/ViewPort/Field/File.pm
+++ b/lib/Reaction/UI/ViewPort/Field/File.pm
@@ -6,9 +6,9 @@ use Reaction::Types::File;
class File is 'Reaction::UI::ViewPort::Field', which {
has '+value' => (isa => 'File', required => 0);
-
- has '+layout' => (default => 'file');
-
+
+ #has '+layout' => (default => 'file');
+
override apply_our_events => sub {
my ($self, $ctx, $events) = @_;
my $value_key = join(':', $self->location, 'value');
diff --git a/lib/Reaction/UI/ViewPort/Field/Number.pm b/lib/Reaction/UI/ViewPort/Field/Number.pm
index e4e925f..f66e03d 100644
--- a/lib/Reaction/UI/ViewPort/Field/Number.pm
+++ b/lib/Reaction/UI/ViewPort/Field/Number.pm
@@ -4,11 +4,11 @@ use Reaction::Class;
class Number is 'Reaction::UI::ViewPort::Field', which {
- has '+layout' => (default => 'textfield');
+ #has '+layout' => (default => 'textfield');
};
-1;
+1;
=head1 NAME
diff --git a/lib/Reaction/UI/ViewPort/Field/Password.pm b/lib/Reaction/UI/ViewPort/Field/Password.pm
index d70ed62..bc86341 100644
--- a/lib/Reaction/UI/ViewPort/Field/Password.pm
+++ b/lib/Reaction/UI/ViewPort/Field/Password.pm
@@ -5,11 +5,11 @@ use Reaction::Class;
class Password is 'Reaction::UI::ViewPort::Field::String', which {
has '+value' => (isa => 'SimpleStr');
- has '+layout' => (default => 'password');
+ #has '+layout' => (default => 'password');
};
-1;
+1;
=head1 NAME
diff --git a/lib/Reaction/UI/ViewPort/Field/String.pm b/lib/Reaction/UI/ViewPort/Field/String.pm
index 4be6bdc..6075592 100644
--- a/lib/Reaction/UI/ViewPort/Field/String.pm
+++ b/lib/Reaction/UI/ViewPort/Field/String.pm
@@ -6,12 +6,12 @@ class String is 'Reaction::UI::ViewPort::Field', which {
has '+value' => (isa => 'Str'); # accept over 255 chars in case, upstream
# constraint from model should catch it
-
- has '+layout' => (default => 'textfield');
+
+ #has '+layout' => (default => 'textfield');
};
-1;
+1;
=head1 NAME
diff --git a/lib/Reaction/UI/ViewPort/Field/Text.pm b/lib/Reaction/UI/ViewPort/Field/Text.pm
index d4e89f8..16d4e56 100644
--- a/lib/Reaction/UI/ViewPort/Field/Text.pm
+++ b/lib/Reaction/UI/ViewPort/Field/Text.pm
@@ -5,11 +5,11 @@ use Reaction::Class;
class Text is 'Reaction::UI::ViewPort::Field', which {
has '+value' => (isa => 'Str');
- has '+layout' => (default => 'textarea');
+ #has '+layout' => (default => 'textarea');
};
-1;
+1;
=head1 NAME
diff --git a/lib/Reaction/UI/ViewPort/Field/TimeRange.pm b/lib/Reaction/UI/ViewPort/Field/TimeRange.pm
index 3619b5e..fb11841 100644
--- a/lib/Reaction/UI/ViewPort/Field/TimeRange.pm
+++ b/lib/Reaction/UI/ViewPort/Field/TimeRange.pm
@@ -9,34 +9,34 @@ use Time::ParseDate ();
class TimeRange is 'Reaction::UI::ViewPort::Field', which {
has '+value' => (isa => 'DateTime::SpanSet');
-
- has '+layout' => (default => 'timerange');
-
- has value_string =>
+
+ #has '+layout' => (default => 'timerange');
+
+ has value_string =>
(isa => 'Str', is => 'rw', lazy_fail => 1, trigger_adopt('value_string'));
-
+
has delete_label => (
isa => 'Str', is => 'rw', required => 1, default => sub { 'Delete' },
);
-
+
has parent => (
isa => 'Reaction::UI::ViewPort::TimeRangeCollection',
is => 'ro',
required => 1,
is_weak_ref => 1
);
-
+
implements build_value_string => as {
my $self = shift;
#return '' unless $self->has_value;
#return $self->value_string;
};
-
+
implements value_array => as {
my $self = shift;
return split(',', $self->value_string);
};
-
+
implements adopt_value_string => as {
my ($self) = @_;
my @values = $self->value_array;
@@ -44,11 +44,11 @@ class TimeRange is 'Reaction::UI::ViewPort::Field', which {
if (length $values[$idx]) {
my ($epoch) = Time::ParseDate::parsedate($values[$idx], UK => 1);
$values[$idx] = DateTime->from_epoch( epoch => $epoch );
- }
+ }
}
$self->value($self->range_to_spanset(@values));
};
-
+
implements range_to_spanset => as {
my ($self, $time_from, $time_to, $repeat_from, $repeat_to, $pattern) = @_;
my $spanset = DateTime::SpanSet->empty_set;
@@ -63,7 +63,7 @@ class TimeRange is 'Reaction::UI::ViewPort::Field', which {
hours => $time_from->hour,
minutes => $time_from->minute,
seconds => $time_from->second );
-
+
delete $args{'days'} if ($pattern eq 'daily');
delete @args{qw/hours days/} if ($pattern eq 'hourly');
$args{'days'} = $time_from->day if ($pattern eq 'monthly');
@@ -80,17 +80,17 @@ class TimeRange is 'Reaction::UI::ViewPort::Field', which {
}
return $spanset;
};
-
+
implements delete => as {
my ($self) = @_;
$self->parent->remove_range_vp($self);
};
-
+
override accept_events => sub { ('value_string', 'delete', super()) };
};
-1;
+1;
=head1 NAME
diff --git a/lib/Reaction/UI/ViewPort/ObjectView.pm b/lib/Reaction/UI/ViewPort/ObjectView.pm
index cbb4c7b..7e1cac1 100644
--- a/lib/Reaction/UI/ViewPort/ObjectView.pm
+++ b/lib/Reaction/UI/ViewPort/ObjectView.pm
@@ -37,7 +37,8 @@ class ObjectView is 'Reaction::UI::ViewPort', which {
push(@field_map, $self->build_fields_for($attr => $args));
}
- $self->_field_map({ @field_map });
+ my %field_map = @field_map;
+ $self->_field_map( \%field_map );
}
};
@@ -94,7 +95,8 @@ class ObjectView is 'Reaction::UI::ViewPort', which {
implements build_ordered_fields => as {
my $self = shift;
- $self->sort_by_spec($self->column_order, [keys %{$self->_field_map_}])};
+ my $ordered = $self->sort_by_spec($self->column_order, [keys %{$self->_field_map}]);
+ return [@{$self->_field_map}{@$ordered}];
};
implements build_simple_field => as {
@@ -152,7 +154,6 @@ class ObjectView is 'Reaction::UI::ViewPort', which {
return $self->build_simple_field(String, $attr, $args);
};
-
implements build_fields_for_type_ArrayRef => as {
my ($self, $attr, $args) = @_;
return $self->build_simple_field(List, $attr, $args)
@@ -168,7 +169,6 @@ class ObjectView is 'Reaction::UI::ViewPort', which {
return $self->build_simple_field(RelatedObject, $attr, $args);
};
-
no Moose;
no strict 'refs';
diff --git a/lib/Reaction/UI/ViewPort/TimeRangeCollection.pm b/lib/Reaction/UI/ViewPort/TimeRangeCollection.pm
index eb1b680..1ebc03b 100644
--- a/lib/Reaction/UI/ViewPort/TimeRangeCollection.pm
+++ b/lib/Reaction/UI/ViewPort/TimeRangeCollection.pm
@@ -11,89 +11,89 @@ use aliased 'Reaction::UI::ViewPort::Field::TimeRange';
class TimeRangeCollection is 'Reaction::UI::ViewPort', which {
- has '+layout' => (default => 'timerangecollection');
-
+ #has '+layout' => (default => 'timerangecollection');
+
has '+column_order' => (
default => sub{[ qw/ time_from time_to pattern repeat_from repeat_to / ]},
);
-
+
has time_from => (
isa => 'Reaction::UI::ViewPort::Field::DateTime',
is => 'rw', lazy_build => 1,
);
-
+
has time_to => (
isa => 'Reaction::UI::ViewPort::Field::DateTime',
is => 'rw', lazy_build => 1,
);
-
+
has repeat_from => (
isa => 'Reaction::UI::ViewPort::Field::DateTime',
is => 'rw', lazy_build => 1,
);
-
+
has repeat_to => (
isa => 'Reaction::UI::ViewPort::Field::DateTime',
is => 'rw', lazy_build => 1,
);
-
+
has pattern => (
isa => 'Reaction::UI::ViewPort::Field::String',
# valid_values => [ qw/none daily weekly monthly/ ],
is => 'rw', lazy_build => 1,
);
-
+
has range_vps => (isa => 'ArrayRef', is => 'rw', lazy_build => 1,);
-
+
has max_range_vps => (isa => 'Int', is => 'rw', lazy_build => 1,);
-
+
has error => (
isa => 'Str',
is => 'rw',
required => 0,
);
-
+
has field_names => (
isa => 'ArrayRef', is => 'rw',
lazy_build => 1, clearer => 'clear_field_names',
);
-
+
has _field_map => (
isa => 'HashRef', is => 'rw', init_arg => 'fields',
clearer => '_clear_field_map',
predicate => '_has_field_map',
set_or_lazy_build('field_map'),
);
-
+
has on_next_callback => (
isa => 'CodeRef',
is => 'rw',
predicate => 'has_on_next_callback',
);
-
+
implements fields => as { shift->_field_map };
-
+
implements build_range_vps => as { [] };
-
+
implements spanset => as {
my ($self) = @_;
my $spanset = DateTime::SpanSet->empty_set;
$spanset = $spanset->union($_->value) for @{$self->range_vps};
return $spanset;
};
-
+
implements range_strings => as {
my ($self) = @_;
return [ map { $_->value_string } @{$self->range_vps} ];
};
-
+
implements remove_range_vp => as {
- my ($self, $to_remove) = @_;
+ my ($self, $to_remove) = @_;
$self->range_vps([ grep { $_ != $to_remove } @{$self->range_vps} ]);
$self->_clear_field_map;
$self->clear_field_names;
};
-
+
implements add_range_vp => as {
my ($self) = @_;
if ($self->can_add) {
@@ -124,7 +124,7 @@ class TimeRangeCollection is 'Reaction::UI::ViewPort', which {
push(@{$self->range_vps}, $field);
}
};
-
+
implements build_field_map => as {
my ($self) = @_;
my %map;
@@ -136,7 +136,7 @@ class TimeRangeCollection is 'Reaction::UI::ViewPort', which {
}
return \%map;
};
-
+
implements build_field_names => as {
my ($self) = @_;
return [
@@ -144,19 +144,19 @@ class TimeRangeCollection is 'Reaction::UI::ViewPort', which {
@{$self->column_order}
];
};
-
+
implements can_add => as {
my ($self) = @_;
my $error;
if ($self->time_to->has_value && $self->time_from->has_value) {
my $time_to = $self->time_to->value;
my $time_from = $self->time_from->value;
-
+
my ($pattern, $repeat_from, $repeat_to) = ('','','');
$pattern = $self->pattern->value if $self->pattern->has_value;
$repeat_from = $self->repeat_from->value if $self->repeat_from->has_value;
$repeat_to = $self->repeat_to->value if $self->repeat_to->has_value;
-
+
my $duration = $time_to - $time_from;
if ($time_to < $time_from) {
$error = 'Please make sure that the Time To is after the Time From.';
@@ -191,7 +191,7 @@ class TimeRangeCollection is 'Reaction::UI::ViewPort', which {
$self->error($error);
return !defined($error);
};
-
+
implements build_simple_field => as {
my ($self, $class, $name, $args) = @_;
return $class->new(
@@ -201,53 +201,53 @@ class TimeRangeCollection is 'Reaction::UI::ViewPort', which {
%$args
);
};
-
+
implements build_time_to => as {
my ($self) = @_;
return $self->build_simple_field(DateTime, 'time_to', {});
};
-
+
implements build_time_from => as {
my ($self) = @_;
return $self->build_simple_field(DateTime, 'time_from', {});
};
-
+
implements build_repeat_to => as {
my ($self) = @_;
return $self->build_simple_field(DateTime, 'repeat_to', {});
};
-
+
implements build_repeat_from => as {
my ($self) = @_;
return $self->build_simple_field(DateTime, 'repeat_from', {});
};
-
+
implements build_pattern => as {
my ($self) = @_;
return $self->build_simple_field(String, 'pattern', {});
};
-
+
implements next => as {
$_[0]->on_next_callback->(@_);
};
-
+
override accept_events => sub {
my $self = shift;
('add_range_vp', ($self->has_on_next_callback ? ('next') : ()), super());
};
-
+
override child_event_sinks => sub {
my ($self) = @_;
return ((grep { ref($_) =~ 'Hidden' } values %{$self->_field_map}),
(grep { ref($_) !~ 'Hidden' } values %{$self->_field_map}),
super());
};
-
+
override apply_events => sub {
my ($self, $ctx, $events) = @_;
-
+
# auto-inflate range fields based on number from hidden field
-
+
my $max = $events->{$self->location.':max_range_vps'};
my @range_vps = map {
TimeRange->new(
@@ -260,15 +260,15 @@ class TimeRangeCollection is 'Reaction::UI::ViewPort', which {
$self->range_vps(\@range_vps);
$self->_clear_field_map;
$self->clear_field_names;
-
+
# call original event handling
-
+
super();
-
- # repack range VPs in case of deletion
-
+
+ # repack range VPs in case of deletion
+
my $prev_idx = -1;
-
+
foreach my $vp (@{$self->range_vps}) {
my $cur_idx = ($vp->name =~ m/range-(\d+)/);
if (($cur_idx - $prev_idx) > 1) {
@@ -283,7 +283,7 @@ class TimeRangeCollection is 'Reaction::UI::ViewPort', which {
};
-1;
+1;
=head1 NAME
@@ -347,11 +347,11 @@ Returns: $spanset consisting of all the TimeRange spans combined
Returns: ArrayRef of Str consisting of the value_strings of all TimeRange
VPs
-
+
=head2 remove_range_vp
Arguments: $to_remove
-
+
=head2 add_range_vp
Arguments: $to_add
diff --git a/lib/Reaction/UI/Widget/ActionForm.pm b/lib/Reaction/UI/Widget/ActionForm.pm
index a631130..1f32afb 100644
--- a/lib/Reaction/UI/Widget/ActionForm.pm
+++ b/lib/Reaction/UI/Widget/ActionForm.pm
@@ -6,9 +6,11 @@ class ActionForm, which {
widget renders [qw/header fields buttons footer/
=> { viewport => func('self','viewport') } ];
- fields renders [viewport over func('viewport','ordered_fields')];
+ fields renders [field over func('viewport','ordered_fields')];
+ field renders [ 'viewport' ];
- buttons renders [ string {"DUMMY"} ], {message => func('viewport','message');
+ buttons renders [ string {"DUMMY"} ],
+ {message => sub{ $_{viewport}->can('message') ? $_{viewport}->message : "" } };
header renders [ string {"DUMMY"} ];
footer renders [ string {"DUMMY"} ];
@@ -18,7 +20,6 @@ class ActionForm, which {
__END__;
-
=head1 NAME
Reaction::UI::Widget::ActionForm
diff --git a/lib/Reaction/UI/Widget/DisplayField.pm b/lib/Reaction/UI/Widget/DisplayField.pm
index c454188..2521dd3 100644
--- a/lib/Reaction/UI/Widget/DisplayField.pm
+++ b/lib/Reaction/UI/Widget/DisplayField.pm
@@ -2,7 +2,7 @@ package Reaction::UI::Widget::DisplayField;
use Reaction::UI::WidgetClass;
-class Text, which {
+class DisplayField, which {
widget renders [ qw/label value/ => { viewport => func(self => 'viewport') } ];
label renders [ string { $_{viewport}->label } ];
value renders [ string { $_{viewport}->value } ];
@@ -10,6 +10,8 @@ class Text, which {
1;
+__END__;
+
=head1 NAME
Reaction::UI::Widget::DisplayField
diff --git a/lib/Reaction/UI/Widget/Field.pm b/lib/Reaction/UI/Widget/Field.pm
index 6425f15..11f2c67 100644
--- a/lib/Reaction/UI/Widget/Field.pm
+++ b/lib/Reaction/UI/Widget/Field.pm
@@ -25,6 +25,8 @@ class Field, which {
1;
+__END__;
+
=head1 NAME
Reaction::UI::Widget::Field
diff --git a/lib/Reaction/UI/Widget/Field/Boolean.pm b/lib/Reaction/UI/Widget/Field/Boolean.pm
index 536764c..a4defcd 100644
--- a/lib/Reaction/UI/Widget/Field/Boolean.pm
+++ b/lib/Reaction/UI/Widget/Field/Boolean.pm
@@ -8,6 +8,8 @@ class Boolean is 'Reaction::UI::Widget::Field', which {
1;
+__END__;
+
=head1 NAME
Reaction::UI::Widget::Field::Boolean
diff --git a/lib/Reaction/UI/Widget/Field/ChooseMany.pm b/lib/Reaction/UI/Widget/Field/ChooseMany.pm
index bd11672..6e9ef47 100644
--- a/lib/Reaction/UI/Widget/Field/ChooseMany.pm
+++ b/lib/Reaction/UI/Widget/Field/ChooseMany.pm
@@ -12,11 +12,13 @@ class ChooseMany is 'Reaction::UI::Widget::Field', which {
available_values renders [ option over func('viewport', 'available_value_choices') ];
selected_values renders [ option over func('viewport', 'current_value_choices') ];
option renders [string {"DUMMY"}], { v_value => sub {$_->{value}}, v_name => sub {$_->{name}} };
+ action_buttons renders [ string {"DUMMY"} ];
};
1;
+__END__;
=head1 NAME
diff --git a/lib/Reaction/UI/Widget/Field/ChooseOne.pm b/lib/Reaction/UI/Widget/Field/ChooseOne.pm
index 7ac1898..9754e71 100644
--- a/lib/Reaction/UI/Widget/Field/ChooseOne.pm
+++ b/lib/Reaction/UI/Widget/Field/ChooseOne.pm
@@ -18,6 +18,7 @@ class ChooseOne is 'Reaction::UI::Widget::Field', which {
1;
+__END__;
=head1 NAME
diff --git a/lib/Reaction/UI/Widget/Field/DateTime.pm b/lib/Reaction/UI/Widget/Field/DateTime.pm
index 9181387..deea805 100644
--- a/lib/Reaction/UI/Widget/Field/DateTime.pm
+++ b/lib/Reaction/UI/Widget/Field/DateTime.pm
@@ -10,6 +10,7 @@ class DateTime is 'Reaction::UI::Widget::Field', which {
1;
+__END__;
=head1 NAME
diff --git a/lib/Reaction/UI/Widget/Field/File.pm b/lib/Reaction/UI/Widget/Field/File.pm
index aa079c7..ad17c83 100644
--- a/lib/Reaction/UI/Widget/Field/File.pm
+++ b/lib/Reaction/UI/Widget/Field/File.pm
@@ -8,6 +8,7 @@ class File is 'Reaction::UI::Widget::Field', which {
1;
+__END__;
=head1 NAME
diff --git a/lib/Reaction/UI/Widget/Field/HiddenArray.pm b/lib/Reaction/UI/Widget/Field/HiddenArray.pm
index 05cdd45..7ccead9 100644
--- a/lib/Reaction/UI/Widget/Field/HiddenArray.pm
+++ b/lib/Reaction/UI/Widget/Field/HiddenArray.pm
@@ -11,6 +11,7 @@ class HiddenArray is 'Reaction::UI::Widget::Field', which {
1;
+__END__;
=head1 NAME
diff --git a/lib/Reaction/UI/Widget/Field/Number.pm b/lib/Reaction/UI/Widget/Field/Number.pm
index 859e7c2..48ef120 100644
--- a/lib/Reaction/UI/Widget/Field/Number.pm
+++ b/lib/Reaction/UI/Widget/Field/Number.pm
@@ -8,6 +8,7 @@ class Number is 'Reaction::UI::Widget::Field', which {
1;
+__END__;
=head1 NAME
diff --git a/lib/Reaction/UI/Widget/Field/Password.pm b/lib/Reaction/UI/Widget/Field/Password.pm
index 3b53b54..7525530 100644
--- a/lib/Reaction/UI/Widget/Field/Password.pm
+++ b/lib/Reaction/UI/Widget/Field/Password.pm
@@ -8,6 +8,7 @@ class Password is 'Reaction::UI::Widget::Field', which {
1;
+__END__;
=head1 NAME
diff --git a/lib/Reaction/UI/Widget/Field/String.pm b/lib/Reaction/UI/Widget/Field/String.pm
index eb25c8f..7e64510 100644
--- a/lib/Reaction/UI/Widget/Field/String.pm
+++ b/lib/Reaction/UI/Widget/Field/String.pm
@@ -8,6 +8,8 @@ class String is 'Reaction::UI::Widget::Field', which {
1;
+__END__;
+
=head1 NAME
Reaction::UI::Widget::Field::String
diff --git a/lib/Reaction/UI/Widget/Field/Text.pm b/lib/Reaction/UI/Widget/Field/Text.pm
index 1066633..9d5e603 100644
--- a/lib/Reaction/UI/Widget/Field/Text.pm
+++ b/lib/Reaction/UI/Widget/Field/Text.pm
@@ -8,6 +8,7 @@ class Text is 'Reaction::UI::Widget::Field', which {
1;
+__END__;
=head1 NAME
diff --git a/lib/Reaction/UI/Widget/Field/TimeRange.pm b/lib/Reaction/UI/Widget/Field/TimeRange.pm
index f96a2c8..bc2ba05 100644
--- a/lib/Reaction/UI/Widget/Field/TimeRange.pm
+++ b/lib/Reaction/UI/Widget/Field/TimeRange.pm
@@ -8,6 +8,7 @@ class TimeRange is 'Reaction::UI::Widget::Field', which {
1;
+__END__;
=head1 NAME
diff --git a/lib/Reaction/UI/Widget/ListView.pm b/lib/Reaction/UI/Widget/ListView.pm
index ab80d93..7d9801c 100644
--- a/lib/Reaction/UI/Widget/ListView.pm
+++ b/lib/Reaction/UI/Widget/ListView.pm
@@ -3,24 +3,24 @@ package Reaction::UI::Widget::ListView;
use Reaction::UI::WidgetClass;
use aliased 'Reaction::UI::ViewPort::ListView' => 'ListView_VP';
-class ListView which {
+class ListView, which {
has 'viewport' => (isa => ListView_VP, is => 'ro', required => 1);
widget renders [
qw(header body) => { viewport => func(self => 'viewport') }
];
-
+
header renders [ header_entry over func(viewport => 'field_names') ];
-
+
header_entry renders [ string { $_{viewport}->field_label_map->{ $_ } } ];
-
+
body renders [ row over func(viewport => 'current_page_collection') ];
-
+
row renders [
col_entry over func(viewport => 'field_names') => { row => $_ }
];
-
+
col_entry renders [
string {
my $proto = $_{row}->$_;
@@ -35,6 +35,8 @@ class ListView which {
1;
+__END__;
+
=head1 NAME
Reaction::UI::Widget::ListView
diff --git a/lib/Reaction/UI/Widget/ObjectView.pm b/lib/Reaction/UI/Widget/ObjectView.pm
index 28614b6..067b73c 100644
--- a/lib/Reaction/UI/Widget/ObjectView.pm
+++ b/lib/Reaction/UI/Widget/ObjectView.pm
@@ -3,8 +3,9 @@ package Reaction::UI::Widget::ObjectView;
use Reaction::UI::WidgetClass;
class ObjectView, which {
- widget renders [ fields => { viewport => func('self', 'viewport') } ];
- fields renders [ viewport over func('viewport','ordered_fields') } ];
+ widget renders [ fields => { viewport => func('self', 'viewport') } ];
+ fields renders [ field over func('viewport', 'ordered_fields') ];
+ field renders [ 'viewport' ];
};
1;
diff --git a/share/skin/default/layout/action_form b/share/skin/default/layout/action_form
index fbbeb17..0e18a36 100644
--- a/share/skin/default/layout/action_form
+++ b/share/skin/default/layout/action_form
@@ -13,6 +13,10 @@
=for layout fields
+<p> [% content %] </p>
+
+=for layout field
+
[% content %] <br />
=for layout buttons
diff --git a/share/skin/default/layout/display_field/boolean b/share/skin/default/layout/display_field/boolean
index dae2f22..74e02e4 100644
--- a/share/skin/default/layout/display_field/boolean
+++ b/share/skin/default/layout/display_field/boolean
@@ -4,10 +4,10 @@
=for layout label
-<strong > [ % content %]: </strong>
+<strong > [% content | html %]: </strong>
=for layout value
-[% content %]
+[% content | html %]
=cut \ No newline at end of file
diff --git a/share/skin/default/layout/display_field/collection b/share/skin/default/layout/display_field/collection
index bea7fa5..3bc65a9 100644
--- a/share/skin/default/layout/display_field/collection
+++ b/share/skin/default/layout/display_field/collection
@@ -5,16 +5,16 @@
=for layout label
-<strong > [ % content %]: </strong>
+<strong > [% content | html %]: </strong>
=for layout list
<ul>
-[% item %]
+[% content %]
</ul>
=for layout item
-<li>[% content %]</li>
+<li>[% content | html %]</li>
=cut
diff --git a/share/skin/default/layout/display_field/date_time b/share/skin/default/layout/display_field/date_time
index e531148..1fcad1a 100644
--- a/share/skin/default/layout/display_field/date_time
+++ b/share/skin/default/layout/display_field/date_time
@@ -4,10 +4,10 @@
=for layout label
-<strong > [ % content %]: </strong>
+<strong> [% content | html %]: </strong>
=for layout value
-[% content %]
+[% content | html %]
=cut
diff --git a/share/skin/default/layout/display_field/list b/share/skin/default/layout/display_field/list
index e000875..2b049b5 100644
--- a/share/skin/default/layout/display_field/list
+++ b/share/skin/default/layout/display_field/list
@@ -5,16 +5,16 @@
=for layout label
-<strong > [ % content %]: </strong>
+<strong > [% content | html %]: </strong>
=for layout list
<ul>
-[% item %]
+[% content %]
</ul>
=for layout item
-<li>[% content %]</li>
+<li>[% content | html %]</li>
=cut \ No newline at end of file
diff --git a/share/skin/default/layout/display_field/number b/share/skin/default/layout/display_field/number
index e531148..1fcad1a 100644
--- a/share/skin/default/layout/display_field/number
+++ b/share/skin/default/layout/display_field/number
@@ -4,10 +4,10 @@
=for layout label
-<strong > [ % content %]: </strong>
+<strong> [% content | html %]: </strong>
=for layout value
-[% content %]
+[% content | html %]
=cut
diff --git a/share/skin/default/layout/display_field/related_object b/share/skin/default/layout/display_field/related_object
index e531148..1fcad1a 100644
--- a/share/skin/default/layout/display_field/related_object
+++ b/share/skin/default/layout/display_field/related_object
@@ -4,10 +4,10 @@
=for layout label
-<strong > [ % content %]: </strong>
+<strong> [% content | html %]: </strong>
=for layout value
-[% content %]
+[% content | html %]
=cut
diff --git a/share/skin/default/layout/display_field/string b/share/skin/default/layout/display_field/string
index dae2f22..831cad4 100644
--- a/share/skin/default/layout/display_field/string
+++ b/share/skin/default/layout/display_field/string
@@ -4,10 +4,10 @@
=for layout label
-<strong > [ % content %]: </strong>
+<strong> [% content | html %]: </strong>
=for layout value
-[% content %]
+[% content | html %]
=cut \ No newline at end of file
diff --git a/share/skin/default/layout/display_field/text b/share/skin/default/layout/display_field/text
index dae2f22..831cad4 100644
--- a/share/skin/default/layout/display_field/text
+++ b/share/skin/default/layout/display_field/text
@@ -4,10 +4,10 @@
=for layout label
-<strong > [ % content %]: </strong>
+<strong> [% content | html %]: </strong>
=for layout value
-[% content %]
+[% content | html %]
=cut \ No newline at end of file
diff --git a/share/skin/default/layout/field/boolean b/share/skin/default/layout/field/boolean
index 2ee1da2..73b817e 100644
--- a/share/skin/default/layout/field/boolean
+++ b/share/skin/default/layout/field/boolean
@@ -18,15 +18,17 @@
=for layout label
<!-- This conditional goes away when mst comes up with something better -->
-[% IF content %]
- <label for="[% id %]"> [% content | html %]: </label>
-[% END %]
+[% content_str = GET content; %]
+[% IF content_str.length; %]
+ <label> [% content_str | html %]: </label>
+[% END; %]
=for layout message
<!-- This conditional goes away when mst comes up with something better -->
-[% IF content %]
- <span> [% content | html %] </span>
+[% content_str = GET content; %]
+[% IF content_str.length; %]
+ <span> [% content_str | html %] </span> <br />
[% END %]
=cut
diff --git a/share/skin/default/layout/field/choose_many b/share/skin/default/layout/field/choose_many
index 8781021..1479de8 100644
--- a/share/skin/default/layout/field/choose_many
+++ b/share/skin/default/layout/field/choose_many
@@ -44,7 +44,7 @@
=for layout action_buttons
-<input type="submit" value="&gt;&gt;" name="[% viewport.event_id_for('add_all_values') | html %]" />
+<input type="submit" value="&gt;&gt;" name="[% viewport.event_id_for('add_all_values') | html %]" /> <br />
<input type="submit" value="&gt;" name="[% viewport.event_id_for('do_add_values') | html %]" /> <br />
<input type="submit" value="&lt;" name="[% viewport.event_id_for('do_remove_values') | html %]" /> <br />
<input type="submit" value="&lt;&lt;" name="[% viewport.event_id_for('remove_all_values') | html %]" /> <br />
@@ -52,15 +52,17 @@
=for layout label
<!-- This conditional goes away when mst comes up with something better -->
-[% IF content %]
- <label> [% content | html %]: </label>
-[% END %]
+[% content_str = GET content; %]
+[% IF content_str.length; %]
+ <label> [% content_str | html %]: </label>
+[% END; %]
=for layout message
<!-- This conditional goes away when mst comes up with something better -->
-[% IF content %]
- <span> [% content | html %] </span> <br />
+[% content_str = GET content; %]
+[% IF content_str.length; %]
+ <span> [% content_str | html %] </span> <br />
[% END %]
=cut
diff --git a/share/skin/default/layout/field/choose_one b/share/skin/default/layout/field/choose_one
index 2378ff5..2fd39d6 100644
--- a/share/skin/default/layout/field/choose_one
+++ b/share/skin/default/layout/field/choose_one
@@ -26,15 +26,17 @@
=for layout label
<!-- This conditional goes away when mst comes up with something better -->
-[% IF content %]
- <label for="[% id | html %]"> [% content | html %]: </label>
-[% END %]
+[% content_str = GET content; %]
+[% IF content_str.length; %]
+ <label> [% content_str | html %]: </label>
+[% END; %]
=for layout message
<!-- This conditional goes away when mst comes up with something better -->
-[% IF content %]
- <span> [% content | html %] </span>
+[% content_str = GET content; %]
+[% IF content_str.length; %]
+ <span> [% content_str | html %] </span> <br />
[% END %]
=cut
diff --git a/share/skin/default/layout/field/date_time b/share/skin/default/layout/field/date_time
index b8dd3ea..4dbd294 100644
--- a/share/skin/default/layout/field/date_time
+++ b/share/skin/default/layout/field/date_time
@@ -10,15 +10,17 @@
=for layout label
<!-- This conditional goes away when mst comes up with something better -->
-[% IF content %]
- <label for="[% id | html %]"> [% content | html %]: </label>
-[% END %]
+[% content_str = GET content; %]
+[% IF content_str.length; %]
+ <label> [% content_str | html %]: </label>
+[% END; %]
=for layout message
<!-- This conditional goes away when mst comes up with something better -->
-[% IF content %]
- <span> [% content | html %] </span>
+[% content_str = GET content; %]
+[% IF content_str.length; %]
+ <span> [% content_str | html %] </span> <br />
[% END %]
=cut
diff --git a/share/skin/default/layout/field/file b/share/skin/default/layout/field/file
index 4c95907..7d323d8 100644
--- a/share/skin/default/layout/field/file
+++ b/share/skin/default/layout/field/file
@@ -9,15 +9,17 @@
=for layout label
<!-- This conditional goes away when mst comes up with something better -->
-[% IF content %]
- <label for="[% id | html %]"> [% content | html %]: </label>
-[% END %]
+[% content_str = GET content; %]
+[% IF content_str.length; %]
+ <label> [% content_str | html %]: </label>
+[% END; %]
=for layout message
<!-- This conditional goes away when mst comes up with something better -->
-[% IF content %]
- <span> [% content | html %] </span>
+[% content_str = GET content; %]
+[% IF content_str.length; %]
+ <span> [% content_str | html %] </span> <br />
[% END %]
=cut
diff --git a/share/skin/default/layout/field/number b/share/skin/default/layout/field/number
index eaa9593..201220f 100644
--- a/share/skin/default/layout/field/number
+++ b/share/skin/default/layout/field/number
@@ -10,15 +10,17 @@
=for layout label
<!-- This conditional goes away when mst comes up with something better -->
-[% IF content %]
- <label for="[% id | html %]"> [% content | html %]: </label>
-[% END %]
+[% content_str = GET content; %]
+[% IF content_str.length; %]
+ <label> [% content_str | html %]: </label>
+[% END; %]
=for layout message
<!-- This conditional goes away when mst comes up with something better -->
-[% IF content %]
- <span> [% content | html %] </span>
+[% content_str = GET content; %]
+[% IF content_str.length; %]
+ <span> [% content_str | html %] </span> <br />
[% END %]
-=cut \ No newline at end of file
+=cut
diff --git a/share/skin/default/layout/field/password b/share/skin/default/layout/field/password
index ec42e2a..e29029a 100644
--- a/share/skin/default/layout/field/password
+++ b/share/skin/default/layout/field/password
@@ -10,15 +10,17 @@
=for layout label
<!-- This conditional goes away when mst comes up with something better -->
-[% IF content %]
- <label for="[% id | html %]"> [% content | html %]: </label>
-[% END %]
+[% content_str = GET content; %]
+[% IF content_str.length; %]
+ <label> [% content_str | html %]: </label>
+[% END; %]
=for layout message
<!-- This conditional goes away when mst comes up with something better -->
-[% IF content %]
- <span> [% content | html %] </span>
+[% content_str = GET content; %]
+[% IF content_str.length; %]
+ <span> [% content_str | html %] </span> <br />
[% END %]
-=cut \ No newline at end of file
+=cut
diff --git a/share/skin/default/layout/field/string b/share/skin/default/layout/field/string
index a17c243..40f3789 100644
--- a/share/skin/default/layout/field/string
+++ b/share/skin/default/layout/field/string
@@ -10,15 +10,17 @@
=for layout label
<!-- This conditional goes away when mst comes up with something better -->
-[% IF content %]
- <label for="[% id | html %]"> [% content | html %]: </label>
-[% END %]
+[% content_str = GET content; %]
+[% IF content_str.length; %]
+ <label> [% content_str | html %]: </label>
+[% END; %]
=for layout message
<!-- This conditional goes away when mst comes up with something better -->
-[% IF content %]
- <span> [% content | html %] </span>
+[% content_str = GET content; %]
+[% IF content_str.length; %]
+ <span> [% content_str | html %] </span> <br />
[% END %]
=cut
diff --git a/share/skin/default/layout/field/text b/share/skin/default/layout/field/text
index 0c6118a..b68ce67 100644
--- a/share/skin/default/layout/field/text
+++ b/share/skin/default/layout/field/text
@@ -12,15 +12,17 @@
=for layout label
<!-- This conditional goes away when mst comes up with something better -->
-[% IF content %]
- <label for="[% id | html %]"> [% content | html %]: </label>
-[% END %]
+[% content_str = GET content; %]
+[% IF content_str.length; %]
+ <label> [% content_str | html %]: </label>
+[% END; %]
=for layout message
<!-- This conditional goes away when mst comes up with something better -->
-[% IF content %]
- <span> [% content | html %] </span>
+[% content_str = GET content; %]
+[% IF content_str.length; %]
+ <span> [% content_str | html %] </span> <br />
[% END %]
=cut
diff --git a/share/skin/default/layout/field/time_range b/share/skin/default/layout/field/time_range
index 7b3bb6b..954c40b 100644
--- a/share/skin/default/layout/field/time_range
+++ b/share/skin/default/layout/field/time_range
@@ -9,15 +9,17 @@ TODO
=for layout label
<!-- This conditional goes away when mst comes up with something better -->
-[% IF content %]
- <label for="[% id | html %]"> [% content | html %]: </label>
-[% END %]
+[% content_str = GET content; %]
+[% IF content_str.length; %]
+ <label> [% content_str | html %]: </label>
+[% END; %]
=for layout message
<!-- This conditional goes away when mst comes up with something better -->
-[% IF content %]
- <span> [% content | html %] </span>
+[% content_str = GET content; %]
+[% IF content_str.length; %]
+ <span> [% content_str | html %] </span> <br />
[% END %]
=cut
diff --git a/share/skin/default/layout/index b/share/skin/default/layout/index
new file mode 100644
index 0000000..9a9bc9c
--- /dev/null
+++ b/share/skin/default/layout/index
@@ -0,0 +1,5 @@
+=for layout widget
+
+<p>I hate programming.</p>
+
+=cut \ No newline at end of file
diff --git a/share/skin/default/layout/layout b/share/skin/default/layout/layout
new file mode 100644
index 0000000..af59032
--- /dev/null
+++ b/share/skin/default/layout/layout
@@ -0,0 +1,56 @@
+=for layout widget
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+
+<head>
+ <title>Component UI Test Title</title>
+
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+ <link rel="stylesheet" type="text/css" href="/static/componentui-basic.css" />
+
+</head>
+
+<body>
+ <div id="container">
+ <div id="header">
+ [% header %]
+ </div>
+
+ <div id="nav">
+ [% menu %]
+ </div>
+
+ <div id="contents">
+ <div id="wrapper">
+ [% sidebar %]
+ [% main_content %]
+ </div>
+ <div class="spacer"></div>
+ </div>
+ </div>
+</body>
+
+</html>
+
+=for layout main_content
+
+ [% content %]
+
+=for layout header
+
+<h1>Component UI Header</h1>
+
+=for layout sidebar
+ <div class="sidebar">
+ [% content %]
+ </div>
+
+=for layout menu
+ <ul class="menu">
+ <li> <a href="/testmodel/foo">Foo</a> </li>
+ <li> <a href="/testmodel/bar">Bar</a> </li>
+ <li> <a href="/testmodel/baz">Baz</a> </li>
+ </ul>
+=cut \ No newline at end of file
diff --git a/share/skin/default/layout/object_view b/share/skin/default/layout/object_view
index 41a16e8..4e6e1b3 100644
--- a/share/skin/default/layout/object_view
+++ b/share/skin/default/layout/object_view
@@ -4,6 +4,12 @@
=for layout fields
- [% content %]<br>
+ <p> [% content %] </p>
+
+=cut
+
+=for layout field
+
+ [% content %] <br>
=cut
diff --git a/share/skin/default/web/componentui-basic.css b/share/skin/default/web/componentui-basic.css
new file mode 100644
index 0000000..a22dbdf
--- /dev/null
+++ b/share/skin/default/web/componentui-basic.css
@@ -0,0 +1,146 @@
+html {
+ min-width: 915px;
+} /*IE7*/
+
+body {
+ color: #393733;
+ margin: 0;
+ padding: 0 20px;
+ text-align: center;
+ background: #DDDDDD;
+}
+
+img {
+ border: none;
+}
+
+p {
+ line-height: 1.4;
+}
+
+input{
+ line-height: 1;
+}
+
+#container {
+ text-align: left;
+ margin: 0 auto;
+ max-width: 1200px;
+ position: relative;
+}
+
+#wrapper {
+ padding: 15px 0 0 19px;
+ min-height: 500px;
+} /*IE6*/
+
+#contents {
+ clear: both;
+ padding: 0 15px 30px 0;
+ margin-top: 7px;
+ background: #FFFFFF;
+}
+
+.spacer{ clear: both; }
+.sidebar {
+ float: right;
+ width: 300px;
+ clear: both;
+ margin: 0 0 2em 0;
+ min-height: 500px;
+}
+.sidebar_section {
+ margin: 1em 0 1em 0;
+ min-height: 100px;
+}
+
+.sidebar_section h2{
+ border-bottom: 2px solid #036;
+ padding: 0 1em 0 0em;
+ font-size: 120%;
+ text-align: right;
+}
+
+#header {
+ background: #036;
+ color: #fff;
+ float: left;
+ width: 100%;
+ margin-bottom: 0px;
+ border-bottom: 1px solid white;
+ position: relative;
+ text-align: left;
+}
+
+#header h1 {
+ font-size: 150%;
+ padding: .2em;
+ margin: .2em;
+}
+
+#nav {
+ background: #036;
+ color: #fff;
+ float: left;
+ width: 100%;
+ margin-bottom: 5px;
+ position: relative;
+ text-align: right;
+}
+
+#nav .menu {
+ display: inline
+ width: 75%;
+ float: left;
+ margin: 0px;
+ padding: 0px;
+ list-style-type: none;
+ color: #FFFFFF;
+ background: #036
+}
+
+#nav .menu li {
+ display: inline;
+}
+
+#nav .menu li a {
+ float: left;
+ width: 7em;
+ color: #FFFFFF;
+ background:color #036;
+ padding: 0.2em .2em;
+ text-decoration: none;
+ border-right: 1px solid #fff;
+ text-align: center;
+ font-size: 105%;
+ font-weight: bold;
+}
+
+#nav .menu li a:hover {
+ background-color: #369;
+ color: #fff;
+}
+
+#login-status{
+ padding: .2em 1em 0 0;
+ font-size: 80%;
+}
+
+#search{
+ float: right;
+ width: 300;
+ padding: 1em;
+}
+#searchbox{
+ line-height: 1.4;
+ font-size: 90%;
+ border: 2px solid #FFF;
+ padding-left: 3px;
+}
+#searchsub{
+ background-color: #036;
+ font-weight: bold;
+ font-size: 90%;
+ color: white;
+ border: 2px solid #369;
+} \ No newline at end of file