package Trog::Routes::HTML;
use strict;
use warnings;
no warnings 'experimental';
use feature qw{signatures};
use Trog::Config;
my $conf = Trog::Config::get();
my $template_dir = 'www/templates';
my $theme_dir;
$theme_dir = "themes/$conf->{'general.theme'}" if $conf->{'general.theme'} && -d "www/themes/$conf->{'general.theme'}";
use lib 'www';
# TODO Things which should be themable
our $landing_page = 'default.tx';
our $htmltitle = 'title.tx';
our $midtitle = 'midtitle.tx';
our $rightbar = 'rightbar.tx';
our $leftbar = 'leftbar.tx';
our $footbar = 'footbar.tx';
our %routes = (
'/' => {
method => 'GET',
callback => \&Trog::Routes::HTML::index,
},
'/setup' => {
method => 'GET',
callback => \&Trog::Routes::HTML::setup,
},
'/login' => {
method => 'GET',
callback => \&Trog::Routes::HTML::login,
},
'/auth' => {
method => 'POST',
callback => \&Trog::Routes::HTML::login,
},
'/config' => {
method => 'GET',
auth => 1,
callback => \&Trog::Routes::HTML::config,
},
'/config/save' => {
method => 'POST',
auth => 1,
callback => \&Trog::Routes::HTML::config,
},
'/post' => {
method => 'GET',
auth => 1,
callback => \&Trog::Routes::HTML::post,
},
'/post/save' => {
method => 'POST',
auth => 1,
callback => \&Trog::Routes::HTML::post,
},
'/posts' => {
method => 'GET',
callback => \&Trog::Routes::HTML::posts,
},
'/files' => {
method => 'GET',
callback => \&Trog::Routes::HTML::files
},
);
# Build aliases for /post with extra data
my @post_aliases = qw{news blog wiki video audio about};
@routes{map { "/$_" } @post_aliases} = map { my %copy = %{$routes{'/posts'}}; $copy{data} = { tag => [$_] }; \%copy } @post_aliases;
# Grab theme routes
if ($theme_dir) {
my $theme_mod = "$theme_dir/routes.pm";
if (-f $theme_mod ) {
require $theme_mod;
@routes{keys(%Theme::routes)} = values(%Theme::routes);
}
}
sub index ($query, $input, $render_cb, $content = '', $i_styles = []) {
$input->{theme_dir} = $theme_dir || '';
my $processor = Text::Xslate->new(
path => $template_dir,
);
my $t_processor;
$t_processor = Text::Xslate->new(
path => "www/$theme_dir/templates",
) if $theme_dir;
$content ||= _pick_processor($rightbar,$processor,$t_processor)->render($landing_page,$input);
my @styles = ('/styles/avatars.css'); #TODO generate file for users
if ($theme_dir) {
unshift(@styles, _themed_style("screen.css")) if -f 'www/'._themed_style("screen.css");
unshift(@styles, _themed_style("structure.css")) if -f 'www/'._themed_style("structure.css");
}
push( @styles, @$i_styles);
#TODO allow theming of print css
return $render_cb->('index.tx',{
user => $query->{user},
theme_dir => $theme_dir,
content => $content,
title => $conf->{'general.title'},
htmltitle => _pick_processor("templates/$htmltitle" ,$processor,$t_processor)->render($htmltitle,$input),
midtitle => _pick_processor("templates/$midtitle" ,$processor,$t_processor)->render($midtitle,$input),
rightbar => _pick_processor("templates/$rightbar" ,$processor,$t_processor)->render($rightbar,$input),
leftbar => _pick_processor("templates/$leftbar" ,$processor,$t_processor)->render($leftbar,$input),
footbar => _pick_processor("templates/$footbar" ,$processor,$t_processor)->render($footbar,$input),
stylesheets => \@styles,
});
}
sub setup ($query, $input, $render_cb) {
return $render_cb->('notconfigured.tx', {
title => 'tCMS Requires Setup to Continue...',
stylesheets => _build_themed_styles('notconfigured.css'),
});
}
sub login ($query, $input, $render_cb) {
# TODO actually do login processing
$query->{failed} //= -1;
return $render_cb->('login.tx', {
title => 'tCMS 2 ~ Login',
to => $query->{to} || '/config',
login_failure => int( $query->{failed} ),
login_message => int( $query->{failed} ) < 1 ? "Login Successful, Redirecting..." : "Login Failed.",
stylesheets => _build_themed_styles('login.css'),
});
}
sub config ($query, $input, $render_cb) {
return $render_cb->('config.tx', {
title => 'Configure tCMS',
stylesheets => _build_themed_styles('config.css'),
});
}
sub config_save ($query, $input, $render_cb) {
return config($query, $input, $render_cb);
}
sub post ($query, $input, $render_cb) {
return $render_cb->('post.tx', {
title => 'New Post',
stylesheets => _build_themed_styles('post.css'),
});
}
sub post_save ($query, $input, $render_cb) {
return post($query, $input, $render_cb);
}
sub posts ($query, $input, $render_cb) {
my $tags = _coerce_array($query->{tag});
require Trog::Data;
my $data = Trog::Data->new($conf);
my $processor ||= Text::Xslate->new(
path => _dir_for_resource('posts.tx'),
);
my $styles = _build_themed_styles('posts.css');
my $content = $processor->render('posts.tx', {
title => "Posts tagged @$tags",
date => 'TODO',
posts => $data->get(
tags => $tags,
like => $query->{like},
),
});
return Trog::Routes::HTML::index($query, $input, $render_cb, $content, $styles);
}
sub files ($query, $input, $render_cb) {
return $render_cb->('fileman.tx', {
title => 'tCMS File Browser',
stylesheets => _build_themed_styles('fileman.css'),
});
}
# Deal with Params which may or may not be arrays
sub _coerce_array ($param) {
my $p = $param || [];
$p = [$param] if $param && (ref $param ne 'ARRAY');
return $p;
}
sub _build_themed_styles ($style) {
my @styles = ("/styles/$style");
my $ts = _themed_style($style);
push(@styles, $ts) if $theme_dir && -f $ts;
return \@styles;
}
sub _pick_processor($file, $normal, $themed) {
return _dir_for_resource($file) eq $template_dir ? $normal : $themed;
}
# Pick appropriate dir based on whether theme override exists
sub _dir_for_resource ($resource) {
return $theme_dir && -f "www/$theme_dir/$resource" ? $theme_dir : $template_dir;
}
sub _themed_style ($resource) {
return _dir_for_resource("styles/$resource")."/styles/$resource";
}
1;