[Jifty-commit] r2205 - in jifty/branches/template-declare: .
lib/Jifty
jifty-commit at lists.jifty.org
jifty-commit at lists.jifty.org
Mon Nov 27 18:49:08 EST 2006
Author: jesse
Date: Mon Nov 27 18:49:08 2006
New Revision: 2205
Added:
jifty/branches/template-declare/lib/Jifty/View/Declare/BaseView.pm
Modified:
jifty/branches/template-declare/ (props changed)
jifty/branches/template-declare/lib/Jifty/ClassLoader.pm
jifty/branches/template-declare/lib/Jifty/View/Declare/Handler.pm
jifty/branches/template-declare/lib/Jifty/View/Declare/Templates.pm
Log:
r45510 at pinglin: jesse | 2006-11-27 18:48:44 -0500
* more work on the declarative views. (Including a first stab at porting the mason templates to T::D.
Help me audrey-tan! (San check at least)
Modified: jifty/branches/template-declare/lib/Jifty/ClassLoader.pm
==============================================================================
--- jifty/branches/template-declare/lib/Jifty/ClassLoader.pm (original)
+++ jifty/branches/template-declare/lib/Jifty/ClassLoader.pm Mon Nov 27 18:49:08 2006
@@ -130,6 +130,11 @@
"use warnings; use strict; package $module;\n"
. "use base qw/Jifty::$1/; sub _autogenerated { 1 };\n"
. "1;" );
+ } elsif ( $module =~ m!^(?:$base)::View$! ) {
+ return $self->return_class(
+ "use warnings; use strict; package $module;\n"
+ . "use base qw/Jifty::View::Declare::Templates/; sub _autogenerated { 1 };\n"
+ . "1;" );
} elsif ( $module =~ m!^(?:$base)::CurrentUser$! ) {
return $self->return_class(
"use warnings; use strict; package $module;\n"
Added: jifty/branches/template-declare/lib/Jifty/View/Declare/BaseView.pm
==============================================================================
--- (empty file)
+++ jifty/branches/template-declare/lib/Jifty/View/Declare/BaseView.pm Mon Nov 27 18:49:08 2006
@@ -0,0 +1,1381 @@
+die "This needs a better name, also to compile and not suck. (This is an unfinished port of our mason templates to Template::Declare";
+__DATA__
+sub __jifty::subs {
+ my ($forever) = get(qw(forever)) || 1;
+
+$r->content_type("text/html; charset=utf-8");
+$r->headers_out->{'Pragma'} = 'no-cache';
+$r->headers_out->{'Cache-control'} = 'no-cache';
+$r->send_http_header;
+
+my $writer = XML::Writer->new;
+$writer->xmlDecl( "UTF-8", "yes" );
+
+my $begin = <<'END';
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/2002/REC-xhtml1-20020801/DTD/xhtml1-strict.dtd">
+<html><head><title></title></head>
+END
+chomp $begin;
+
+
+if ($forever) {
+ my $whitespace = " " x ( 1024 - length $begin );
+ $begin =~ s/<body>$/$whitespacebody/s;
+}
+
+$m->print($begin);
+$m->flush_buffer;
+$writer->startTag("body");
+
+
+ while (1) {
+ my $sent = write_subs_once($writer);
+ flush STDOUT;
+ last if ($sent && !$forever);
+ sleep 1;
+ }
+ $writer->endTag();
+ return;
+
+
+
+}
+
+sub write_subs_once {
+ my $writer = shift;
+ Jifty::Subs::Render->render(
+ Jifty->web->session->id,
+ sub {
+ my ( $mode, $name, $content ) = @_;
+ $writer->startTag( "pushfrag", mode => $mode );
+ $writer->startTag( "fragment", id => $name );
+ $writer->dataElement( "content", $content );
+ $writer->endTag();
+ $writer->endTag();
+ }
+ );
+}
+
+sub __jifty::admin::_elements::nav {
+
+ my $nav = Jifty->web->navigation->child(
+ "Administration" => url => '/__jifty/admin/' );
+ foreach my $model ( Jifty->class_loader->models ) {
+ next unless $model->isa('Jifty::Record');
+ next unless ( $model =~ /^(?:.*)::(.*?)$/ );
+ my $type = $1;
+ $nav->child( $type => url => '/__jifty/admin/model/' . $type );
+ }
+ return;
+}
+
+sub __jifty::admin::action::dhandler {
+ my $action_class = Jifty->api->qualify( $m->dhandler_arg );
+
+ my $action = new_action(
+ class => $action_class,
+ moniker => "run-$action_class",
+ );
+
+ $action->sticky_on_failure(1);
+ wrapper {
+
+ form {
+
+ for ( $action->argument_names ) {
+ param( $action, $_ );
+ }
+
+ submit( label => _("Run the action") );
+ }
+
+ h2 { _('Done?') };
+ hyperlink(
+ url => "/__jifty/admin/",
+ label => _('Back to the admin console')
+ );
+
+ }
+}
+
+sub __jifty::admin::autohandler {
+
+# If "AdminMode" is turned off in Jifty's config file, don't let people at the admin UI.
+unless (Jifty->config->framework('AdminMode')) {
+ redirect('/__jifty/error/permission_denied');
+ return;
+}
+show ('admin::elements::nav'); # XXX TODO hm. should be in dispatcher.
+}
+
+sub __jifty::admin::fragments::list::list {
+my ( $object_type $page $new_slot $item_path ) = get(qw( object_type page new_slot item_path ));
+
+$page ||= 1;
+$new_slot = 1 unless defined $new_slot;
+$item_path ||= "/__jifty/admin/fragments/list/view"
+
+my $collection_class = Jifty->app_class("Model", $object_type."Collection");
+my $search = Jifty->web->response->result('search');
+my $collection;
+if(!$search) {
+ $collection = $collection_class->new();
+ $collection->unlimit();
+} else {
+ $collection = $search->content('search');
+ warn $collection->build_select_query;
+}
+
+$collection->set_page_info( current_page => $page,
+ per_page => 25
+ );
+my $search_region = Jifty::Web::PageRegion->new(
+ name => 'search',
+ path => '/__jifty/empty',
+);
+
+ hyperlink(
+ onclick => [{
+ region => $search_region->qualified_name,
+ replace_with => '/__jifty/admin/fragments/list/search',
+ toggle => 1,
+ args => { object_type => $object_type }
+ },
+ ],
+ label => 'Toggle search'
+ );
+
+ $search_region->render ;
+
+ if ($collection->pager->last_page > 1) {
+ with ( class => "page-count"), span { _('Page [_1] of [_2]', $page , $collection->pager->last_page)}
+ }
+
+ if ($collection->pager->total_entries == 0) {
+ _('No items found')
+ }
+
+with ( class => "list"), div {
+while ( my $item = $collection->next ) {
+ Jifty->web->region(
+ name => 'item-' . $item->id,
+ path => $item_path,
+ defaults => { id => $item->id, object_type => $object_type }
+ );
+}
+
+}
+
+with ( class => "paging"), div {
+ if ($collection->pager->previous_page) {
+with ( class => "prev-page"), span {
+ hyperlink( label => "Previous Page", onclick => { args => { page => $collection->pager->previous_page } } );
+}
+ }
+ if ($collection->pager->next_page) {
+with ( class => "next-page"), span {
+ hyperlink( label => "Next Page", onclick => { args => { page => $collection->pager->next_page } } )
+}
+ }
+}
+
+ if ($new_slot) {
+ Jifty->web->region(
+ name => 'new_item',
+ path => "/__jifty/admin/fragments/list/new_item",
+ defaults => { object_type => $object_type },
+ )
+
+}
+
+
+}
+
+# When you hit "save" and create a item, you want to put a fragment
+# containing the new item in the associated list and refresh the current
+# fragment
+#
+sub __jifty::admin::fragments::list::new_item {
+my ( $object_type, $region) = get(qw(object_type region));
+my $record_class = Jifty->app_class("Model", $object_type);
+ my $create = new_action(class => 'Create'.$object_type);
+with ( class => "jifty_admin create item inline"), div {
+ foreach my $argument ($create->argument_names) {
+ param ($create=>$argument);
+}
+}
+
+Jifty->web->form->submit(
+ label => 'Create',
+ onclick => [
+ { submit => $create },
+ { refresh_self => 1 },
+ {
+ element => $region->parent->get_element('div.list'),
+ append => '/__jifty/admin/fragments/list/view',
+ args => {
+ object_type => $object_type,
+ id => { result_of => $create, name => 'id' },
+ },
+ },
+ ]
+ )
+
+}
+
+sub __jifty::admin::fragments::list::search {
+my (
+$object_type
+) = get(qw(object_type));
+my $search = new_action(
+ class => "Search".$object_type,
+ moniker => "search",
+ sticky_on_success => 1,
+);
+
+with ( class => "jifty_admin"), div {
+ for my $arg ($search->argument_names) {
+ param($search => $arg);
+ }
+
+ $search->button(
+ label => 'Search!',
+ onclick => {
+ submit => $search,
+ refresh => Jifty->web->current_region->parent,
+ args => { page => 1}
+ }
+ )
+hr {};
+}
+}
+
+sub __jifty::admin::fragments::list::update {
+my ( $id $object_type) = get(qw(id object_type));
+my $record_class = Jifty->app_class("Model", $object_type);
+my $record = $record_class->new();
+my $update = new_action(
+ class => "Update".$object_type,
+ moniker => "update-" . Jifty->web->serial,
+ record => $record
+);
+with ( class => "jifty_admin update item inline $object_type">, div {
+with ( class => "editlink"), div {
+ hyperlink(
+ label => _("Save"),
+ onclick => [
+ { submit => $update },
+ { replace_with => '/__jifty/admin/fragments/list/view',
+ args => { object_type => $object_type, id => $id }
+ }
+ ]
+ )
+
+ hyperlink(
+ label => _("Cancel"),
+ onclick => {
+ replace_with => '/__jifty/admin/fragments/list/view',
+ args => { object_type => $object_type, id => $id }
+ },
+ as_button => 1
+ )
+
+};
+
+ foreach my $argument ($update->argument_names) {
+ param($update=>$argument);
+}
+hr {};
+}
+
+}
+
+sub __jifty::admin::fragments::list::view {
+my (
+$id => undef
+$object_type
+) = get(qw());
+my $record_class = Jifty->app_class("Model", $object_type);
+my $record = $record_class->new();
+$record->load($id);
+my $update = new_action(
+ class => "Update".$object_type,
+ moniker => "update-" . Jifty->web->serial,
+ record => $record
+);
+my $delete = new_action(
+ class => "Delete".$object_type,
+ moniker => "delete-" . Jifty->web->serial,
+ record => $record
+);
+
+with ( class => "jifty_admin read item inline"), div {
+
+ Jifty->web->form->submit(
+ class => "editlink",
+ label => "Delete",
+ submit => $delete,
+ onclick => {
+ confirm => _("Confirm delete?"),
+ delete => Jifty->web->current_region->qualified_name
+ },
+ );
+ hyperlink(
+ label => "Edit",
+ class => "editlink",
+ onclick => {
+ replace_with => "/__jifty/admin/fragments/list/update",
+ args => { object_type => $object_type, id => $id }
+ },
+ as_button => 1
+ );
+
+ $delete->hidden('id',$id) ;
+ foreach my $argument ($update->argument_names) {
+ unless( $argument =~ /_confirm$/
+ && lc $update->arguments->{$argument}{render_as} eq 'password') {
+ param($update => $argument, render_mode => 'read');
+ }
+ };
+
+hr {};
+}
+
+}
+
+sub __jifty::admin::index {
+ with( title => 'Jifty Administrative Console' ), wrapper {
+
+ h1 { _('Database Administration') };
+
+ p {
+ _( 'This console lets you manage the records in your Jifty database. Below, you should see a list of all your database tables. Feel free to go through and add, delete or modify records.'
+ );
+ };
+
+ p {
+ _( q{To disable this administrative console, add "framework: AdminMode: 0" to your application's configuration file.}
+ );
+ };
+
+ h2 { _('Models') };
+ ul {
+ foreach my $model ( Jifty->class_loader->models ) {
+ next unless $model->isa('Jifty::Record');
+ next unless ( $model =~ /^(?:.*)::(.*?)$/ );
+ my $type = $1;
+ li {
+ hyperlink(
+ url => '/__jifty/admin/model/' . $type,
+ label => $type
+ );
+ }
+ }
+ }
+ h2 { _('Actions') } ul {
+ foreach my $action ( Jifty->api->actions ) {
+ Jifty::Util->require($action);
+ next
+ if ($action->can('autogenerated')
+ and $action->autogenerated );
+ li {
+ hyperlink(
+ url => '/__jifty/admin/action/' . $action,
+ label => $action
+ );
+ }
+ }
+ }
+ h2 { _('Done?') } Jifty->web->return(
+ to => "/",
+ label => 'Back to the application'
+ );
+ }
+}
+
+sub __jifty::admin::model::dhandler {
+my $object_type = $m->dhandler_arg;
+
+my $collection_class = Jifty->app_class("Model", $object_type."Collection");
+my $records = $collection_class->new();
+$records->unlimit;
+wrapper {
+h1 {_('Manage records: [_1]',$object_type) };
+form {
+ Jifty->web->region(name => "admin-$object_type",
+ path => "/__jifty/admin/fragments/list/list",
+ defaults => { object_type => $object_type ,
+ render_submit => 1 });
+
+ };
+
+h2 {_('Done?')}
+ hyperlink( url => "/__jifty/admin/", label => 'Back to the admin console');
+
+}
+}
+
+sub __jifty::autocomplete.xml {
+# Note: the only point to this file is to set the content_type; the actual
+# behavior is accomplished inside the framework. It will go away once we
+# have infrastructure for serving things of various content-types.
+$r->content_type('text/xml; charset=UTF-8');
+my $ref = Jifty->web->response->result('autocomplete')->content;
+my @options = @{$ref->{'completions'}||[]};
+body {
+ul {
+% foreach my $item ( @options) {
+% if (!ref($item)) {
+li {<% $item %>}
+% } elsif (exists $item->{label}) {
+li {with ( class => "informal"), span {<% $item->{label} %>}with ( class => "hidden_value"), span {<% $item->{value} %>}}
+% } else {
+li {<% $item->{value} %>}
+% }
+%}
+}
+</body>
+}
+
+sub __jifty::css::dhandler {
+if ( $m->dhandler_arg !~ /^[0-9a-f]{32}\.css$/ ) {
+ # This doesn't look like a real request for squished CSS,
+ # so redirect to a more failsafe place
+ Jifty->web->redirect( "/static/css/" . $m->dhandler_arg );
+}
+
+Jifty->web->generate_css;
+
+use HTTP::Date ();
+
+if ( Jifty->handler->cgi->http('If-Modified-Since')
+ and $m->dhandler_arg eq Jifty->web->cached_css_digest . '.css' )
+{
+ Jifty->log->debug("Returning 304 for cached css");
+ $r->header_out( Status => 304 );
+ return;
+}
+
+$r->content_type("text/css");
+$r->header_out( 'Expires' => HTTP::Date::time2str(time + 31536000) );
+
+# XXX TODO: If we start caching the squished CSS in a file somewhere, we
+# can have the static handler serve it, which would take care of gzipping
+# for us.
+use Compress::Zlib qw();
+
+if ( Jifty::View::Static::Handler->client_accepts_gzipped_content ) {
+ Jifty->log->debug("Sending gzipped squished CSS");
+ $r->header_out( "Content-Encoding" => "gzip" );
+ binmode STDOUT;
+ print Compress::Zlib::memGzip( Jifty->web->cached_css );
+}
+else {
+ Jifty->log->debug("Sending squished CSS");
+ print Jifty->web->cached_css;
+}
+return;
+}
+
+sub __jifty::empty {
+}
+
+sub __jifty::error::_elements::error_text {
+h1 {Sorry, something went awry}
+p { For one reason or another, you got to a web page that caused a bit
+of an error. And then you got to our "basic" error handler. Which
+means we haven't written a pretty, easy to understand error message
+for you just yet. The message we <em>do</em> have is:}
+
+<blockquote>
+<b><% $error %></b>
+</blockquote>
+
+p { There's a pretty good chance that error message doesn't mean
+anything to you, but we'd rather you have a little bit of information
+about what went wrong than nothing. We've logged this error, so we
+know we need to write something friendly explaining just what happened
+and how to fix it.}
+
+p { For now <% hyperlink( url =>"/", label => 'head on back
+home')%> and try to forget that we let you down.}
+my (
+$error
+) = get(qw());}
+
+sub __jifty::error::_elements::wrapper {
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+<head>
+ <title>Mason error</title>
+ <link rel="stylesheet" type="text/css" href="/__jifty/error/error.css" media="all" />
+</head>
+body {
+ with ( id => "headers"), div {
+ <h1 class="title">Mason error}
+ }
+ with ( id => "content"), div {
+ <a name="content"></a>
+% if (Jifty->config->framework('AdminMode') ) {
+with ( class => "warning admin_mode"), div {
+Alert: Jifty <% Jifty->web->tangent( label => 'administration mode' , url => '/__jifty/admin/')%> is enabled.
+}
+% }
+ <% Jifty->web->render_messages %>
+
+ <% $m->content |n%>
+
+ }
+</body>
+</html>
+<%doc>
+
+This exists as a fallback wrapper, in case the mason error in question
+is caused by the Jifty app's wrapper, for instance.
+
+</%doc>}
+
+sub __jifty::error::autohandler {
+<%flags>
+inherit => undef
+</%flags>
+% $m->call_next}
+
+sub __jifty::error::dhandler {
+Jifty->log->error("Unhandled web error ". $m->dhandler_arg);
+<&|/_elements/wrapper, title => 'Something went awry' &>
+
+<& _elements/error_text, error => $m->dhandler_arg &>
+
+</&>
+}
+
+sub __jifty::error::error.css {
+$r->content_type("text/css");
+h1 {
+ color: red;
+}
+
+}
+sub __jifty::error::mason_internal_error {
+my $wrapper = "/_elements/wrapper";
+
+my $cont = Jifty->web->request->continuation;
+$wrapper = "/__jifty/error/_elements/wrapper"
+ if $cont
+ and $cont->request->path eq "/__jifty/error/mason_internal_error";
+
+# If we're not in devel, bail
+if ( not Jifty->config->framework("DevelMode") or not $cont ) {
+ $m->comp(
+ $wrapper,
+ content => sub {
+ $m->comp( "_elements/error_text", error => "mason internal error" );
+ },
+ title => "Something went awry"
+ );
+ $m->abort;
+}
+
+my $e = $cont->response->error;
+my $msg = $e->message;
+$msg =~ s/, <\S+> (line|chunk) \d+\././;
+
+my $info = $e->analyze_error;
+my $file = $info->{file};
+my @lines = @{ $info->{lines} };
+my @stack = @{ $info->{frames} };
+<&| $wrapper, title => "Mason error" &>
+
+Error in <& .line, file => $file, line => "@lines" &>
+<pre><% $msg %></pre>
+
+<% Jifty->web->return( label => "Try again" ) %>
+
+h2 {Call stack};
+ul {
+% for my $frame (@stack) {
+% next if $frame->filename =~ m{/HTML/Mason/};
+ li {<& .line, file => $frame->filename, line => $frame->line &>}
+% }
+}
+
+</&>
+
+<%def .line>
+my (
+$file
+$line
+) = get(qw());
+% if (-w $file) {
+% my $path = $file;
+% for (map {$_->[1]} @{Jifty->handler->mason->interp->comp_root}) {
+% last if $path =~ s/^\Q$_\E//;
+% }
+% if ($path ne $file) {
+template <% Jifty->web->tangent( url =>"/__jifty/edit/mason_component$path",
+ label => "$path line ".$line,
+ parameters => { line => $line } ) %>
+% } else {
+<% Jifty->web->tangent( url =>"/__jifty/edit/library$path",
+ label => "$path line ".$line,
+ parameters => { line => $line } ) %>
+% }
+% } else {
+<% $file %> line <% $line %>
+% }
+</%def>
+
+}
+
+sub __jifty::halo {
+for my $id (0..$#stack) {
+ my @kids;
+ my $looking = $id;
+ while (++$looking <= $#stack and $stack[$looking]->{depth} >= $stack[$id]->{depth} + 1) {
+ push @kids, {id => $stack[$looking]{id}, path => $stack[$looking]{path}, render_time => $stack[$looking]{render_time}}
+ if $stack[$looking]->{depth} == $stack[$id]->{depth} + 1;
+ }
+ $stack[$id]{kids} = \@kids;
+
+ if ($stack[$id]{depth} > 1) {
+ $looking = $id;
+ $looking-- while ($stack[$looking]{depth} >= $stack[$id]{depth});
+ $stack[$id]{parent} = {id => $stack[$looking]{id}, path => $stack[$looking]{path}, render_time => $stack[$looking]{render_time}};
+ }
+}
+
+my $depth = 0;
+
+ div {outs('<a href="#" id="render_info" onclick="Element.toggle('render_info_tree'); return false">Page info</a>')};
+with( style=>"display: none" , id=> "render_info_tree"), div {
+ foreach my $item (@stack) {
+ if ( $item->{depth} > $depth ) {
+ul {
+ } elsif ( $item->{depth} < $depth ) {
+ for ($item->{depth}+1 .. $depth) {
+}}
+ }
+}
+ } elsif ( $item->{depth} == $depth ) {
+}
+ }
+
+li {
+ outs('<a href="#" class="halo_comp_info"
+ onmouseover="halo_over('<% $item->{id} %>')"
+ onmouseout="halo_out('<% $item->{id} %>')"
+ onclick="halo_toggle('<% $item->{id} %>'); return false;">
+<% $item->{'name'} %> - <% $item->{'render_time'} %></a>');
+ unless ($item->{subcomponent}) {
+Jifty->web->tangent( url =>"/__jifty/edit/mason_component/".$item->{'path'}, label => 'Edit') ;
+ }
+ $depth = $item->{'depth'};
+ }
+
+ for (1 .. $depth) {
+}}
+ }
+}
+
+% foreach my $item (@stack) {
+<& .frame, frame => $item &>
+% }
+my ( @stack) = get(qw(stack));
+
+
+
+<%def .frame>
+with ( class => "halo_actions" id="halo-<% $id %), div {-menu" style="display: none; top: 5px; left: 500px; min-width: 200px; width: 300px; z-index: 5;">
+<h1 id="halo-<% $id %>-title">
+ <span style="float: right;"><a href="#" onclick="halo_toggle('<% $id %>'); return false">[ X ]</a>}
+ <% $frame->{name} %>
+}
+<div style="position: absolute; bottom: 3px; right: 3px">with ( class => "resize" title="Resize" id="halo-<% $id %), span {-resize">}}
+
+with ( class => "body"), div {
+with ( class => "path"), div {<% $frame->{path} %>}
+with ( class => "time"), div {Rendered in <% $frame->{'render_time'} %>s}
+}
+% if ($frame->{parent}) {
+with ( class => "section"), div {Parent}
+with ( class => "body"), div {ul {
+li {<a href="#" class="halo_comp_info" onmouseover="halo_over('<% $frame->{parent}{id} %>')"
+ onmouseout="halo_out('<% $frame->{parent}{id} %>')"
+ onclick="halo_toggle('<% $frame->{parent}{id} %>'); return false;">
+<% $frame->{parent}{'path'} %> - <% $frame->{parent}{'render_time'} %></a>}
+}}
+% }
+% if (@{$frame->{kids}}) {
+with ( class => "section"), div {Children}
+with ( class => "body"), div {ul {
+% for my $item (@{$frame->{kids}}) {
+li {<a href="#" class="halo_comp_info" onmouseover="halo_over('<% $item->{id} %>')"
+ onmouseout="halo_out('<% $item->{id} %>')"
+ onclick="halo_toggle('<% $item->{id} %>'); return false;">
+<% $item->{'path'} %> - <% $item->{'render_time'} %></a>}
+% }
+}
+}
+% }
+% if (@args) {
+with ( class => "section"), div {Variables}
+with ( class => "body"), div {<ul class="fixed">
+% for my $e (@args) {
+li {<b><% $e->[0] %></b>:
+% if ($e->[1]) {
+% my $expanded = Jifty->web->serial;
+<a href="#" onclick="Element.toggle('<% $expanded %>'); return false"><% $e->[1] %></a>
+with ( id => "<% $expanded %), div {" style="display: none; position: absolute; left: 200px; border: 1px solid black; background: #ccc; padding: 1em; padding-top: 0; width: 300px; height: 500px; overflow: auto"><pre><% Jifty::YAML::Dump($e->[2]) %></pre>}
+% } elsif (defined $e->[2]) {
+<% $e->[2] %>
+% } else {
+<i>undef</i>
+% }
+}
+% }
+}}
+% }
+% if (@stmts) {
+with ( class => "section"), div {<%_('SQL Statements')%>}
+with ( class => "body" style="height: 300px; overflow: auto"), div {ul {
+% for (@stmts) {
+li {
+with ( class => "fixed"), span {<% $_->[1] %>}<br />
+% if (@{$_->[2]}) {
+<b>Bindings:</b> <tt><% join(',', map {defined $_ ? ($_ =~ /[^[:space:][:graph:]]/ ? "*BLOB*" : $_ ) : "undef"} @{$_->[2]}) %></tt><br />
+% }
+<i><% _('%1 seconds', $_->[3]) %></i>
+}
+ }
+}}
+ }
+with ( class => "section"), div {
+ unless ($frame->{subcomponent}) {
+Jifty->web->tangent( url =>"/__jifty/edit/mason_component/".$frame->{'path'}, label => 'Edit');
+ } else {
+outs(' ');
+% }
+}
+}
+my ( $frame) = get(qw(frame));
+my $id = $frame->{id};
+
+my @args;
+while (my ($key, $value) = splice(@{$frame->{args}},0,2)) {
+ push @args, [$key, ref($value), $value];
+}
+ at args = sort {$a->[0] cmp $b->[0]} @args;
+
+my $prev = '';
+my @stmts = @{$frame->{'sql_statements'}};
+</%def>
+}
+
+sub __jifty::js::dhandler {
+ if ( $m->dhandler_arg !~ /^[0-9a-f]{32}\.js$/ ) {
+
+ # This doesn't look like a real request for squished JS,
+ # so redirect to a more failsafe place
+ Jifty->web->redirect( "/static/js/" . $m->dhandler_arg );
+ }
+
+ Jifty->web->generate_javascript;
+
+ use HTTP::Date ();
+
+ if ( Jifty->handler->cgi->http('If-Modified-Since')
+ and $m->dhandler_arg eq Jifty->web->cached_javascript_digest . '.js' )
+ {
+ Jifty->log->debug("Returning 304 for cached javascript");
+ $r->header_out( Status => 304 );
+ return;
+ }
+
+ $r->content_type("application/x-javascript");
+ $r->header_out( 'Expires' => HTTP::Date::time2str( time + 31536000 ) );
+
+ # XXX TODO: If we start caching the squished JS in a file somewhere, we
+ # can have the static handler serve it, which would take care of gzipping
+ # for us.
+ use Compress::Zlib qw();
+
+ if ( Jifty::View::Static::Handler->client_accepts_gzipped_content ) {
+ Jifty->log->debug("Sending gzipped squished JS");
+ $r->header_out( "Content-Encoding" => "gzip" );
+ binmode STDOUT;
+ print Compress::Zlib::memGzip( Jifty->web->cached_javascript );
+ } else {
+ Jifty->log->debug("Sending squished JS");
+ print Jifty->web->cached_javascript;
+ }
+ return;
+}
+
+sub __jifty::online_docs::autohandler {
+
+# If "AdminMode" is turned off in Jifty's config file, don't let people at the admin UI.
+ unless ( Jifty->config->framework('AdminMode') ) {
+ $m->redirect('/__jifty/error/permission_denied');
+ $m->abort();
+ }
+
+ $m->call_next();
+}
+
+sub __jifty::online_docs::content.html {
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" >
+<head>
+<title><% _( $n || 'Jifty') %> - <%_('Jifty Pod Online')%></title>
+<style type="text/css"><!--
+a { text-decoration: none }
+a:hover { text-decoration: underline }
+a:focus { background: #99ff99; border: 1px black dotted }
+--></style>
+</head>
+body {
+<%PERL>
+my $jifty_dirname = Jifty::Util->jifty_root."/";
+my $app_dirname = Jifty::Util->app_root."/lib/";
+$n =~ s/::/\//g;
+
+my @options = (
+ $app_dirname.$n.".pod",
+ $app_dirname.$n.".pm",
+ $jifty_dirname.$n.".pod",
+ $jifty_dirname.$n.".pm");
+
+my $total_body;
+foreach my $file (@options) {
+ next unless -r "$file";
+ local $/;
+ my $fh;
+ open $fh, "$file" or next;
+ $total_body = <$fh>;
+ close $fh;
+}
+my $body;
+my $schema;
+my $converter = Pod::Simple::HTML->new();
+if($n !~ /^Jifty\//) {
+ if ($total_body =~ /package (.*?)::Schema;(.*)package/ismx) {
+ $schema = $2;
+ }
+}
+
+
+$converter->output_string( \$body );
+$converter->parse_string_document($total_body);
+$body =~ s{.*?<body [^>]+>}{}s;
+$body =~ s{</body>\s*</html>\s*$}{};
+$n =~ s{/}{::}g;
+$m->print("h1 {$n}");
+$m->print("h2 {"._('Schema')."}<pre>$schema</pre>") if ($schema);
+$body =~ s{<a href="http://search\.cpan\.org/perldoc\?(Jifty%3A%3A[^"]+)"([^>]*)>}{<a href="content.html?n=$1"$2>}g;
+$body =~ s!}\n\tul { !ul { !;
+$body =~ s!}!}}!;
+$body =~ s!p { }!!;
+$body =~ s!<a name=!<a id=!g;
+$body =~ s!__index__!index!g;
+$m->print($body);
+</%PERL>
+</body></html>
+<%ARGS>
+$Target => '&method=content'
+$n => 'Jifty'
+</%ARGS>
+require File::Basename;
+require File::Find;
+require File::Temp;
+require File::Spec;
+require Pod::Simple::HTML;
+}
+
+sub __jifty::online_docs::index.html {
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN"
+"http://www.w3.org/TR/html4/">
+<html lang="en">
+<head>
+<title><%_( $n || 'Jifty') %> - <%_('Online Documentation')%></title>
+<style type="text/css"><!--
+a { text-decoration: none }
+a:hover { text-decoration: underline }
+a:focus { background: #99ff99; border: 1px black dotted }
+--></style>
+</head>
+<FRAMESET COLS="*, 250">
+ <FRAME src="./content.html" name="podcontent">
+ <FRAME src="./toc.html" name="podtoc">
+ <NOFRAMES>
+ <a style="display: none" href="#toc"><%_('Table of Contents')%></a>
+<& content.html, Target => '' &>
+ h1 {<a id="toc"><%_('Table of Contents')%></a>}
+<& toc.html, Target => '' &>
+ </NOFRAMES>
+</FRAMESET>
+my (
+$n => undef
+) = get(qw());
+}
+
+sub __jifty::online_docs::toc.html {
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" >
+<head>
+<title><% _($n || 'Jifty') %> - <%_('Jifty Developer Documentation Online')%></title>
+<style type="text/css"><!--
+a { text-decoration: none }
+a:hover { text-decoration: underline }
+a:focus { background: #99ff99; border: 1px black dotted }
+--></style>
+</head>
+<body style="background: #dddddd">
+<%PERL>
+my @found;
+File::Find::find(
+ { untaint => 1,
+ wanted => sub {
+ return unless /(\w+)\.(?:pm|pod)$/;
+ my $name = $File::Find::name;
+ $name =~ s/.*lib\b.//;
+ $name =~ s!\.(?:pm|pod)!!i;
+ $name =~ s!\W!::!g;
+ push @found, $name;
+ },follow => ($^O ne 'MSWin32') },
+ Jifty::Util->app_root ."/lib",
+);
+
+
+File::Find::find(
+ { untaint => 1,
+ wanted => sub {
+ return unless $File::Find::name =~ /^(?:.*?)(Jifty.*?\.(?:pm|pod))$/;
+ my $name = $1;
+ $name =~ s/.*lib\b.//;
+ $name =~ s!\.(?:pm|pod)!!i;
+ $name =~ s!\/!::!g;
+ push @found, $name;
+ },follow => ($^O ne 'MSWin32') },
+ Jifty::Util->jifty_root,
+);
+
+my $indent = 0;
+my $prev = '';
+foreach my $file (sort @found) {
+ my ($parent, $name) = ($1, $2) if $file =~ /(?:(.*)::)?(\w+)$/;
+ $parent = '' unless defined $parent;
+ if ($file =~ /^$prev\::(.*)/) {
+ my $foo = $1;
+ while ($foo =~ s/(\w+):://) {
+ $indent++;
+ $m->print((' ' x $indent));
+ $m->print("$1<br />");
+ }
+ $indent++;
+ } elsif ($prev !~ /^$parent\::/) {
+ $indent = 0 unless length $parent;
+ while ($parent =~ s/(\w+)//) {
+ next if $prev =~ s/\b$1:://;
+ while ($prev =~ s/:://) {
+ $indent--;
+ }
+ $m->print((' ' x $indent));
+ $m->print("$1<br />");
+ $indent++;
+ }
+ } elsif ($prev =~ /^$parent\::(.*::)/) {
+ my $foo = $1;
+ while ($foo =~ s/:://) {
+ $indent--;
+ }
+ }
+ $m->print( ( ' ' x $indent )
+ . '<a target="podcontent" href="content.html?n=' . $file . '">' . $name
+ . '</a><br />' ."\n" );
+ $prev = $file;
+}
+
+</%PERL>
+</body></html>
+<%INIT>
+require File::Basename;
+require File::Find;
+require File::Temp;
+require File::Spec;
+require Pod::Simple::HTML;
+</%INIT>
+<%ARGS>
+$n => ''
+$method => ''
+$Target => '&method=content'
+</%ARGS>
+}
+
+sub __jifty::validator.xml {
+$r->content_type('text/xml; charset=UTF-8');
+
+my $output = "";
+use XML::Writer;
+my $writer = XML::Writer->new( OUTPUT => \$output );
+$writer->xmlDecl( "UTF-8", "yes" );
+$writer->startTag("validation");
+for my $ra ( Jifty->web->request->actions ) {
+ my $action = Jifty->web->new_action_from_request($ra);
+ $writer->startTag( "validationaction", id => $action->register_name );
+ for my $arg ( $action->argument_names ) {
+ if ( not $action->arguments->{$arg}->{ajax_validates} ) {
+ $writer->emptyTag( "ignored", id => $action->error_div_id($arg) );
+ $writer->emptyTag( "ignored", id => $action->warning_div_id($arg) );
+ } elsif ( not $action->arguments->{$arg}->{mandatory}
+ and (not defined $action->argument_value($arg)
+ or length $action->argument_value($arg) == 0 ) ) {
+ $writer->emptyTag( "blank", id => $action->error_div_id($arg) );
+ $writer->emptyTag( "blank", id => $action->warning_div_id($arg) );
+ } elsif ( $action->result->field_error($arg) ) {
+ $writer->dataElement(
+ "error",
+ $action->result->field_error($arg),
+ id => $action->error_div_id($arg)
+ );
+ $writer->emptyTag( "ok", id => $action->warning_div_id($arg) );
+ } elsif ( $action->result->field_warning($arg) ) {
+ $writer->dataElement(
+ "warning",
+ $action->result->field_warning($arg),
+ id => $action->warning_div_id($arg)
+ );
+ $writer->emptyTag( "ok", id => $action->error_div_id($arg) );
+ } else {
+ $writer->emptyTag( "ok", id => $action->error_div_id($arg) );
+ $writer->emptyTag( "ok", id => $action->warning_div_id($arg) );
+ }
+ }
+ $writer->endTag();
+ $writer->startTag( "canonicalizeaction", id => $action->register_name );
+ for my $arg ( $action->argument_names ) {
+ if ($ra->arguments->{$arg} eq $action->argument_value($arg) ) {
+ # if the value doesn't change, it can be ignored.
+ # canonicalizers can change other parts of the action, so we want to send all changes
+ $writer->emptyTag( "ignored", name => $action->form_field_name($arg) );
+ } elsif ( not defined $action->argument_value($arg)
+ or length $action->argument_value($arg) == 0 ) {
+ $writer->emptyTag( "blank", name => $action->form_field_name($arg) );
+ } else {
+ if ( $action->result->field_canonicalization_note($arg) ) {
+ $writer->dataElement(
+ "canonicalization_note",
+ $action->result->field_canonicalization_note($arg),
+ id => $action->canonicalization_note_div_id($arg)
+ );
+ }
+ $writer->dataElement(
+ "update",
+ $action->argument_value($arg),
+ name => $action->form_field_name($arg)
+ );
+ }
+ }
+ $writer->endTag();
+}
+$writer->endTag();
+$m->out($output);
+$m->abort();
+}
+
+sub __jifty::webservices::xml {
+my $output = "";
+my $writer = XML::Writer->new( OUTPUT => \$output, UNSAFE => 1 );
+$writer->xmlDecl( "UTF-8", "yes" );
+$writer->startTag("response");
+for my $f ( Jifty->web->request->fragments ) {
+ # Set up the region stack
+ local Jifty->web->{'region_stack'} = [];
+ my @regions;
+ do {
+ push @regions, $f;
+ } while ($f = $f->parent);
+
+ for $f (reverse @regions) {
+ my $new = Jifty->web->get_region( join '-', grep {$_} Jifty->web->qualified_region, $f->name );
+
+ # Arguments can be complex mapped hash values. Get their
+ # real values by mapping.
+ my %defaults = %{$f->arguments || {}};
+ for (keys %defaults) {
+ my ($key, $value) = Jifty::Request::Mapper->map(destination => $_, source => $defaults{$_});
+ delete $defaults{$_};
+ $defaults{$key} = $value;
+ }
+
+ $new ||= Jifty::Web::PageRegion->new(
+ name => $f->name,
+ path => $f->path,
+ region_wrapper => $f->wrapper,
+ parent => Jifty->web->current_region,
+ defaults => \%defaults,
+ );
+ $new->enter;
+ }
+
+ # Stuff the rendered region into the XML
+ $writer->startTag( "fragment", id => Jifty->web->current_region->qualified_name );
+ my %args = %{ Jifty->web->current_region->arguments };
+ $writer->dataElement( "argument", $args{$_}, name => $_) for sort keys %args;
+ $writer->cdataElement( "content", Jifty->web->current_region->as_string );
+ $writer->endTag();
+
+ Jifty->web->current_region->exit while Jifty->web->current_region;
+}
+
+my %results = Jifty->web->response->results;
+for (keys %results) {
+ $writer->startTag("result", moniker => $_, class => $results{$_}->action_class);
+ $writer->dataElement("success", $results{$_}->success);
+
+ $writer->dataElement("message", $results{$_}->message) if $results{$_}->message;
+ $writer->dataElement("error", $results{$_}->error) if $results{$_}->error;
+
+ my %warnings = $results{$_}->field_warnings;
+ my %errors = $results{$_}->field_errors;
+ my %fields; $fields{$_}++ for keys(%warnings), keys(%errors);
+ for (sort keys %fields) {
+ next unless $warnings{$_} or $errors{$_};
+ $writer->startTag("field", name => $_);
+ $writer->dataElement("warning", $warnings{$_}) if $warnings{$_};
+ $writer->dataElement("error", $errors{$_}) if $errors{$_};
+ $writer->endTag();
+ }
+
+ # XXX TODO: Hack because we don't have a good way to serialize
+ # Jifty::DBI::Record's yet, which are technically circular data
+ # structures at some level (current_user of a
+ # current_user->user_object is itself)
+ use Scalar::Util qw(blessed);
+ my $content = $results{$_}->content;
+
+ sub stripkids {
+ my $top = shift;
+ if ( not ref $top ) { return $top }
+ elsif (
+ blessed($top)
+ and ( $top->isa("Jifty::DBI::Record")
+ or $top->isa("Jifty::DBI::Collection") )
+ )
+ {
+ return undef;
+ } elsif ( ref $top eq 'HASH' ) {
+ foreach my $item ( keys %$top ) {
+ $top->{$item} = stripkids( $top->{$item} );
+ }
+ } elsif ( ref $top eq 'ARRAY' ) {
+ for ( 0 .. $#{$top} ) {
+ $top->[$_] = stripkids( $top->[$_] );
+ }
+ }
+ return $top;
+ }
+
+ $content = stripkids($content);
+ use XML::Simple;
+ $writer->raw(XML::Simple::XMLout($content, NoAttr => 1, RootName => "content", NoIndent => 1))
+ if keys %{$content};
+
+ $writer->endTag();
+}
+
+$writer->endTag();
+$r->content_type('text/xml; charset=utf-8');
+outs($output);
+}
+
+sub __jifty::webservices::yaml {
+ $r->content_type("text/x-yaml");
+ outs( Jifty::YAML::Dump( { Jifty->web->response->results } ) );
+}
+
+sub _elements::header {
+ my ($title) = get(qw(title));
+ $r->content_type('text/html; charset=utf-8');
+ head {
+ with(
+ 'http-equiv' => "content-type",
+ content => "text/html; charset=utf-8"
+ ),
+ meta {};
+ with( name => 'robots', content => 'all' ), meta {};
+ title { _($title) };
+
+ Jifty->web->include_css;
+ Jifty->web->include_javascript;
+ }
+}
+
+sub _elements::keybindings {
+ with( id => "keybindings" ), div {};
+}
+
+sub _elements::menu {
+ my ($menu) = get(qw(menu));
+
+ # Default to the app menu
+ $menu ||= Jifty->web->navigation;
+ my @children = $menu->children;
+ if (@children) {
+ with( class => "menu" ), ul {
+ show( ".menu", item => $_ );
+ }
+ }
+
+}
+sub _elements::_menu {
+ my ($item) = get(qw(item));
+ my @kids = $item->children;
+ my @params;
+ if ( $item->active ) {
+ push @params, class => "active";
+ }
+
+ with(@params), li {
+
+ $item->as_link;
+
+ if (@kids) {
+ with( class => "submenu" ), ul {
+ show( ".menu", item => $_ ) for @kids;
+ }
+ };
+ }
+
+}
+
+sub _elements::nav {
+ my $top = Jifty->web->navigation;
+ $top->child( Home => url => "/", sort_order => 1 );
+ if ( Jifty->config->framework('AdminMode') ) {
+ $top->child(
+ Administration =>
+ url => "/__jifty/admin/",
+ sort_order => 998
+ );
+ $top->child(
+ OnlineDocs =>
+ url => "/__jifty/online_docs/",
+ label => 'Online docs',
+ sort_order => 999
+ );
+ }
+ return ();
+}
+
+sub _elements::page_nav {
+ if ( @{ Jifty->web->page_navigation->children } ) {
+ with( class => "page_nav" ), div {
+ show( _elements::menu, menu => Jifty->web->page_navigation );
+ }
+ }
+}
+
+sub _elements::sidebar {
+ with( id => "salutation" ), div {
+ if ( Jifty->web->current_user->id
+ and Jifty->web->current_user->user_object )
+ {
+ my $u = Jifty->web->current_user->user_object;
+ my $method = $u->_brief_description;
+ _( 'Hiya, %1.', $u->$method() );
+ } else {
+ _(q{You're not currently signed in.});
+ }
+ };
+ with( id => "navigation" ), div {
+ show( '_elements::menu', menu => Jifty->web->navigation );
+ }
+}
+
+sub _elements::wrapper {
+% Jifty->handler->stash->{'in_body'} = 0;
+my ( $title ) = get(qw(title));
+# First we set up the header.
+# now that we've printed out the header, we're inside the body, so it's safe to print
+# halo markers.
+Jifty->handler->stash->{'in_body'} = 1;
+outs('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">');
+with ( xmlns=> "http://www.w3.org/1999/xhtml" 'xml:lang'=>"en"), html {
+
+ with (title => $title), show (_elements::header);
+
+body {
+ with ( id => "headers"), div {
+ <%hyperlink( url => "/", label => _(Jifty->config->framework('ApplicationName')))%>
+ <h1 class="title"><% _($title) %>}
+ }
+ <& sidebar &>
+ with ( id => "content"), div {
+ with (name => 'content'), a{};
+ if (Jifty->config->framework('AdminMode') ) {
+with ( class => "warning admin_mode"), div {
+outs(_('Alert'). ':' . Jifty->web->tangent( label => _('Administration mode is enabled.') , url => '/__jifty/admin/'));
+}
+ }
+ <% Jifty->web->render_messages %>
+ <% $m->content |n%>
+ <& /_elements/keybindings &>
+ }
+ with ( id => "jifty-wait-message" style="display: none"), div {<%_('Loading...')%>}
+ Jifty::Mason::Halo->render_component_tree() if (Jifty->config->framework('DevelMode') );
+# This is required for jifty server push. If you maintain your own
+# wrapper, make sure you have this as well.
+ if ( Jifty->config->framework('PubSub')->{'Enable'} && Jifty::Subs->list ) {
+script {outs('new Jifty.Subs({}).start();')};
+ }
+}
+}
+}
+
+sub autohandler { # XXX TODO MOVE INTO DISPATCHER
+$r->content_type('text/html; charset=utf-8');
+
+if ($m->base_comp->path =~ m|/_elements/|) {
+ # Requesting an internal component by hand -- naughty
+ $m->redirect("/errors/requested_private_component");
+}
+$m->comp('/_elements/nav');
+}
+
+sub dhandler {
+ Jifty->log->error( "404: user tried to get to " . $m->dhandler_arg );
+ $r->header_out( Status => '404' );
+ with( title => _("Something's not quite right") ), wrapper => {
+
+ with( id => "overview" ),
+ div {
+ p {
+ join( " ",
+ _("You got to a page that we don't think exists."),
+ _("Anyway, the software has logged this error."),
+ _("Sorry about this . ") );
+ }
+
+ p { hyperlink( url => " / ", label => _('Go back home...') ) }
+
+ }
+ };
+}
+
+sub index {
+ with( title => _('Welcome to your new Jifty application') ), wrapper {
+ with(
+ src => "/static/images/pony.jpg",
+ alt => _( 'You said you wanted a pony. (Source %1)',
+ 'http://hdl.loc.gov/loc.pnp/cph.3c13461')
+ ),
+ img {};
+ }
+}
+
Modified: jifty/branches/template-declare/lib/Jifty/View/Declare/Handler.pm
==============================================================================
--- jifty/branches/template-declare/lib/Jifty/View/Declare/Handler.pm (original)
+++ jifty/branches/template-declare/lib/Jifty/View/Declare/Handler.pm Mon Nov 27 18:49:08 2006
@@ -52,7 +52,7 @@
my $template = pop @components;
my $package = join('::',$self->root_class,grep { $_ } @components);
- Jifty::Util->require($package);
+ Jifty::Util->require($package) ;
unless ( $package->isa('Jifty::View::Declare::Templates') ) {
$self->log->error( "$package (" . $self->root_class . " / $templatename) isn't a valid template package." );
return undef;
Modified: jifty/branches/template-declare/lib/Jifty/View/Declare/Templates.pm
==============================================================================
--- jifty/branches/template-declare/lib/Jifty/View/Declare/Templates.pm (original)
+++ jifty/branches/template-declare/lib/Jifty/View/Declare/Templates.pm Mon Nov 27 18:49:08 2006
@@ -8,7 +8,8 @@
use base qw/Template::Declare/;
our @EXPORT = qw(form hyperlink tangent redirect new_action form_submit form_next_page request get param current_user render_action);
-
+{
+no warnings qw/redefine/;
sub form (&){
my $code = shift;
outs(Jifty->web->form->start);
@@ -16,7 +17,7 @@
outs(Jifty->web->form->end);
return ''
}
-
+}
sub hyperlink(@) {
outs (Jifty->web->link(@_));
More information about the Jifty-commit
mailing list