diff options
Diffstat (limited to 'rt/share/html/Admin/Tools')
-rw-r--r-- | rt/share/html/Admin/Tools/Configuration.html | 95 | ||||
-rw-r--r-- | rt/share/html/Admin/Tools/Queries.html | 2 | ||||
-rw-r--r-- | rt/share/html/Admin/Tools/Shredder/Elements/ObjectCheckBox | 4 | ||||
-rw-r--r-- | rt/share/html/Admin/Tools/Shredder/Elements/PluginHelp | 4 | ||||
-rw-r--r-- | rt/share/html/Admin/Tools/Shredder/autohandler | 4 | ||||
-rw-r--r-- | rt/share/html/Admin/Tools/Theme.html | 219 | ||||
-rw-r--r-- | rt/share/html/Admin/Tools/index.html | 2 |
7 files changed, 240 insertions, 90 deletions
diff --git a/rt/share/html/Admin/Tools/Configuration.html b/rt/share/html/Admin/Tools/Configuration.html index f60cdba6f..fea3a5fcc 100644 --- a/rt/share/html/Admin/Tools/Configuration.html +++ b/rt/share/html/Admin/Tools/Configuration.html @@ -87,7 +87,7 @@ foreach my $key ( RT->Config->Options( Overridable => undef, Sorted => 0 ) ) { <tr class="<% $index_conf%2 ? 'oddline' : 'evenline'%>"> <td class="collection-as-table"><% $key %></td> <td class="collection-as-table"> -% if ( $key =~ /Password(?!Length)/i ) { +% if ( $key =~ /Password/i and $key !~ /MinimumPasswordLength|AllowLoginPasswordAutoComplete/ ) { <em><% loc('Password not printed' ) %></em>\ % } else { <% stringify($val) |n %>\ @@ -150,6 +150,7 @@ for my $type (qw/Tickets Queues Transactions Groups PrivilegedUsers Unprivileged $class =~ s/Privileged|Unprivileged//; my $collection = $class->new(RT->SystemUser); $collection->UnLimit; + $collection->FindAllRows; # find disabled if ($type =~ /PrivilegedUsers/) { $user_count = $collection->CountAll; $collection->LimitToPrivileged; @@ -179,6 +180,15 @@ for my $type (qw/Tickets Queues Transactions Groups PrivilegedUsers Unprivileged </ol> </&> +<&|/Widgets/TitleBox, title => loc("Static file search order") &> +<ol> +% foreach my $path ( (map {$_->{root}} RT->Config->Get('StaticRoots')), +% RT::Interface::Web->StaticRoots ) { +<li><% $path %></li> +% } +</ol> +</&> + <&|/Widgets/TitleBox, title => loc("Perl library search order") &> <ol> % foreach my $inc (@INC) { @@ -187,6 +197,22 @@ for my $type (qw/Tickets Queues Transactions Groups PrivilegedUsers Unprivileged </ol> </&> +<&|/Widgets/TitleBox, title=> loc("Loaded config files") &> +<ol> +% foreach my $config (RT->Config->LoadedConfigs) { +% if ($config->{site}) { +<li><strong><% $config->{filename} %></strong></li> +% } else { +<li><% $config->{filename} %></li> +% } +% } +</ol> +</&> + +<&|/Widgets/TitleBox, title=> loc("Logging summary") &> + <& /Admin/Elements/LoggingSummary &> +</&> + </td> </table> @@ -199,6 +225,7 @@ for my $type (qw/Tickets Queues Transactions Groups PrivilegedUsers Unprivileged % my $attrs = $RT::System->Attributes; % my $index_size = 0; % while ( my $attr = $attrs->Next ) { +% next if $attr->Name eq 'UpgradeHistory'; <tr class="<% $index_size%2 ? 'oddline' : 'evenline'%>"> % if ($attr->Name eq 'UserLogo') { % my $content = $attr->Content; @@ -249,6 +276,10 @@ if ($item =~ /^\s*(.*?)\s*v(\S+);/) { </table> </&> +<&|/Widgets/TitleBox, title => loc("RT upgrade history")&> +<& /Admin/Elements/UpgradeHistory &> +</&> + <&|/Widgets/TitleBox, title => loc("Perl configuration") &> % require Config; <pre> @@ -256,6 +287,66 @@ if ($item =~ /^\s*(.*?)\s*v(\S+);/) { </pre> </&> +<&|/Widgets/TitleBox, title=> loc("Environment variables") &> +<table border="0" cellspacing="0" cellpadding="5" width="100%" class="collection"> +<tr class="collection-as-table"> +<th class="collection-as-table"><&|/l&>Variable</&></th> +<th class="collection-as-table"><&|/l&>Value</&></th> +</tr> +% my $row = 0; +% for my $key (sort keys %ENV) { +<tr class="collection-as-table <% $row++ %2 ? 'oddline' : 'evenline'%>"> +<td class="collection-as-table"><% $key %></td> +<td class="collection-as-table"><% $ENV{$key} %></td> +</tr> +% } +</table> +</&> + +<&|/Widgets/TitleBox, title => loc("Operating System") &> +<table border="0" cellspacing="0" cellpadding="5" width="100%" class="collection"> +<tr class="collection-as-table evenline"> +<td class="collection-as-table">Deployment type</td> +<td class="collection-as-table"><% + $INC{'mod_perl.pm'} ? "mod_perl" : + $INC{'FCGI.pm'} ? "fastcgi" : + "standalone" %> +</td> +</tr> +<%perl> +my @os = ( + "Distribution" => 'lsb_release --all', + "uname -a" => 'uname -a', + "SELinux status" => 'getenforce', + "Apache" => [map { "$_ -V" } qw(apache2ctl apachectl httpdctl)], + "nginx" => 'nginx -V 2>&1', + "lighttpd" => 'lighttpd -V', +); +my @os_info; + +while (my ($name, $cmd) = splice @os, 0, 2) { + $cmd = [$cmd] unless ref $cmd eq 'ARRAY'; + for my $run (@$cmd) { + $run .= " </dev/null"; + $run .= " 2>/dev/null" unless $run =~ /2>/; + my $result = `$run`; + if (defined $result and $result =~ /\S/) { + push @os_info, $name => $result; + last; + } + } +} +my $row = 1; +</%perl> +% while (my ($name, $output) = splice @os_info, 0, 2) { +<tr class="collection-as-table <% $row++ % 2 ? "oddline" : "evenline" %>"> +<td class="collection-as-table"><% $name %></td> +<td class="collection-as-table" style="white-space: pre-wrap; font-family: monospace"><% $output %></td> +</tr> +% } +</table> +</&> + <%INIT> use Data::Dumper; local $Data::Dumper::Terse = 1; @@ -264,7 +355,7 @@ local $Data::Dumper::Indent = 2; sub stringify { my $value = shift; my $output = Dumper $value; - RT::Interface::Web::EscapeUTF8(\$output); + RT::Interface::Web::EscapeHTML(\$output); $output =~ s/ / /g; $output =~ s!\n!<br />!g; return $output; diff --git a/rt/share/html/Admin/Tools/Queries.html b/rt/share/html/Admin/Tools/Queries.html index 23025ec4b..66427dedf 100644 --- a/rt/share/html/Admin/Tools/Queries.html +++ b/rt/share/html/Admin/Tools/Queries.html @@ -53,7 +53,7 @@ unless ($session{'CurrentUser'}->HasRight( Object=> $RT::System, Right => 'Super </%init> <& /Admin/Elements/Header, Title => $title &> <& /Elements/Tabs &> -<script type="text/javascript" src="<%RT->Config->Get('WebPath')%>/NoAuth/js/jquery.tablesorter.min.js"></script> +<script type="text/javascript" src="<%RT->Config->Get('WebPath')%>/static/js/jquery.tablesorter.min.js"></script> <&|/Widgets/TitleBox, title => loc('SQL Queries') &> % my $history = $RT::Handle->QueryHistory; diff --git a/rt/share/html/Admin/Tools/Shredder/Elements/ObjectCheckBox b/rt/share/html/Admin/Tools/Shredder/Elements/ObjectCheckBox index 757e10658..e333d0779 100644 --- a/rt/share/html/Admin/Tools/Shredder/Elements/ObjectCheckBox +++ b/rt/share/html/Admin/Tools/Shredder/Elements/ObjectCheckBox @@ -48,12 +48,12 @@ <%ARGS> $Object => undef </%ARGS> -<input type="checkbox" name="WipeoutObject" value="<% $Object->_AsString %>" /> +<input type="checkbox" name="WipeoutObject" value="<% $Object->UID %>" /> <span> % if( $m->comp_exists( $path ) ) { % $m->comp( $path, Object => $Object ); % } else { -<% $Object->_AsString %> +<% $Object->UID %> % } </span><br /> <%ONCE> diff --git a/rt/share/html/Admin/Tools/Shredder/Elements/PluginHelp b/rt/share/html/Admin/Tools/Shredder/Elements/PluginHelp index bf37a890a..cc082767a 100644 --- a/rt/share/html/Admin/Tools/Shredder/Elements/PluginHelp +++ b/rt/share/html/Admin/Tools/Shredder/Elements/PluginHelp @@ -59,8 +59,8 @@ my %plugins = $plugin_obj->List; <%INIT> my $file = $plugins{ $Plugin }; unless( $file ) { - $RT::Logger->error( "Couldn't find plugin '$Plugin'" ); - return; + $RT::Logger->error( "Couldn't find plugin '$Plugin'" ); + return; } use RT::Shredder::POD qw(); diff --git a/rt/share/html/Admin/Tools/Shredder/autohandler b/rt/share/html/Admin/Tools/Shredder/autohandler index 62909b0c3..9a5ecd106 100644 --- a/rt/share/html/Admin/Tools/Shredder/autohandler +++ b/rt/share/html/Admin/Tools/Shredder/autohandler @@ -47,13 +47,13 @@ %# END BPS TAGGED BLOCK }}} <%INIT> unless( $session{'CurrentUser'}->HasRight( Right => 'SuperUser', Object => $RT::System ) ) { - return $m->comp( 'Elements/Error/NoRights' ); + return $m->comp( 'Elements/Error/NoRights' ); } use RT::Shredder (); my $path = RT::Shredder->StoragePath; unless( -d $path && -w _ ) { - return $m->comp( 'Elements/Error/NoStorage', Path => $path ); + return $m->comp( 'Elements/Error/NoStorage', Path => $path ); } $m->call_next(%ARGS); diff --git a/rt/share/html/Admin/Tools/Theme.html b/rt/share/html/Admin/Tools/Theme.html index 83f88a98b..3a0c71b35 100644 --- a/rt/share/html/Admin/Tools/Theme.html +++ b/rt/share/html/Admin/Tools/Theme.html @@ -51,7 +51,7 @@ <& /Elements/Tabs &> <& /Elements/ListActions, actions => \@results &> -<script type="text/javascript" src="<%RT->Config->Get('WebPath')%>/NoAuth/js/farbtastic.js"></script> +<script type="text/javascript" src="<%RT->Config->Get('WebPath')%>/static/js/farbtastic.js"></script> <div id="simple-customize"> <div id="upload-logo"> @@ -61,26 +61,31 @@ <label for="logo-upload"><&|/l&>Upload a new logo</&>:</label> <input type="file" name="logo-upload" id="logo-upload" /><br /> <div class="gd-support"> -% if (%gd_can) { +% if ($valid_image_types) { <&|/l, $valid_image_types &>Your system supports automatic color suggestions for: [_1]</&> % } else { <&|/l&>GD is disabled or not installed. You can upload an image, but you won't get automatic color suggestions.</&> % } </div> - <input name="reset_logo" value="Reset to default RT Logo" type="submit" /> - <input type="submit" value="Upload" /> + <input name="reset_logo" value="<&|/l&>Reset to default RT Logo</&>" type="submit" /> + <input type="submit" value="<&|/l&>Upload</&>" /> </form> </div> <div id="customize-theme"> - <h2>Customize the RT theme</h2> + <h2><&|/l&>Customize the RT theme</&></h2> <ol> <li> <label for="section"><&|/l&>Select a section</&>:</label> <select id="section"></select> </li> <li> - <div class="description"><&|/l&>Select a color for the section</&>:</div> + <div class="description"> + <&|/l&>Select a color for the section</&>: + <div id="logo-picker-hint" style="display: none;"> + <&|/l&>You can also click on the logo above to get colors!</&> + </div> + </div> % if ($colors) { <div class="primary-colors"> % for (@$colors) { @@ -93,27 +98,29 @@ </div> % } <div id="color-picker"></div> + <canvas id="logo-color-picker" title="<&|/l&>Click to choose a color</&>"></canvas> </li> </ol> </div> </div> <div id="custom-css"> - <h2>Custom CSS (Advanced)</h2> - + <h2><&|/l&>Custom CSS (Advanced)</&></h2> + <form method="POST"> <textarea rows=20 id="user_css" name="user_css" wrap="off"><% $user_css %></textarea><br /> - <input id="try" type="button" class="button" value="Try" /> - <input id="reset" type="reset" value="Reset" type="submit" /> - <input name="reset_css" value="Reset to default RT Theme" type="submit" /> - <input value="Save" type="submit" /> + <input id="try" type="button" class="button" value="<&|/l&>Try</&>" /> + <input id="reset" type="reset" value="<&|/l&>Reset</&>" type="submit" /> + <input name="reset_css" value="<&|/l&>Reset to default RT Theme</&>" type="submit" /> + <input value="<&|/l&>Save</&>" type="submit" /> </form> </div> <%ONCE> my @sections = ( - ['Page' => ['body']], - ['Header' => ['div#quickbar', 'body.aileron #main-navigation #app-nav > li, body.aileron #main-navigation #app-nav > li > a, #prefs-menu > li, #prefs-menu > li > a, #logo .rtname']], + ['Page' => ['body', 'div#body']], + ['Menu bar' => ['div#quickbar', '#main-navigation #app-nav.sf-shadow > li, #main-navigation #app-nav.sf-shadow > li > a, #prefs-menu > li, #prefs-menu > li > a, #logo .rtname']], + ['Title bar' => ['div#header']], ['Page title' => ['div#header h1']], ['Page content' => ['div#body']], ['Buttons' => ['input[type="reset"], input[type="submit"], input[class="button"]']], @@ -173,7 +180,7 @@ jQuery(function($) { newcss += "; border: none;" /* Page title's text color is the selected color */ - if (applying[name].match(/#header/)) + if (applying[name].match(/h1/)) newcss = "color: " + bg; /* Nav doesn't need a background, but it wants text color */ @@ -193,7 +200,35 @@ jQuery(function($) { change_color($(this).css('background-color'), $(this).css('color')); }); - + // Setup the canvas color picker + $("#logo-theme-editor img").load(function() { + var logo = $(this); + var canvas = $("#logo-color-picker"); + var el_canvas = canvas.get(0); + + if (!el_canvas.getContext) return; + + var context = el_canvas.getContext("2d"); + el_canvas.width = logo.width(); + el_canvas.height = logo.height(); + context.drawImage(logo.get(0), 0, 0); + + logo.hide().after(canvas); + canvas.show().click(function(ev) { + ev.preventDefault(); + var R = 0, + G = 1, + B = 2, + A = 3; + var pixel = this.getContext("2d").getImageData(ev.offsetX, ev.offsetY, 1, 1).data; + // Farbtastic expects values in the range of 0..1 + var rgba = $.makeArray(pixel).map(function(v,i) { return v / 255 }); + var wheel = $.farbtastic("#color-picker"); + wheel.setHSL( wheel.RGBToHSL( rgba.slice(R,A) ) ); + // XXX TODO factor in the alpha channel too + }); + $('#logo-picker-hint').show(); + }); }); </script> <%INIT> @@ -207,14 +242,82 @@ my $text_threshold = 0.6; my @results; my $imgdata; +my $colors; +my $valid_image_types; +if (not RT->Config->Get('DisableGD') and Convert::Color->require) { + require GD; + + # Always find out what GD can read... + my %gd_can; + for my $type (qw(Png Jpeg Gif)) { + $gd_can{$type}++ if GD::Image->can("newFrom${type}Data"); + } + $valid_image_types = join(", ", map { uc } sort { lc $a cmp lc $b } keys %gd_can); +} + +my $analyze_img = sub { + return undef unless $valid_image_types; + + my $imgdata = shift; + return undef unless $imgdata; + + # ...but only analyze the image if we have data + my $img = GD::Image->new($imgdata); + unless ($img) { + # This has to be one damn long line because the loc() needs to be + # source parsed correctly. + push @results, loc("Automatically suggested theme colors aren't available for your image. This might be because you uploaded an image type that your installed version of GD doesn't support. Supported types are: [_1]. You can recompile libgd and GD.pm to include support for other image types.", $valid_image_types); + return undef; + } + + my %colors; + + my @wsamples; + my @hsamples; + if ($img->width > 200) { + @wsamples = map { int($img->width*($_/200)) } (0..199); + } else { + @wsamples = ( 0 .. $img->width - 1 ); + } + if ($img->height > 200) { + @hsamples = map { int($img->height*($_/200)) } (0..199); + } else { + @hsamples = ( 0 .. $img->height - 1 ); + } + for my $i (@wsamples) { + for my $j (@hsamples) { + my @color = $img->rgb( $img->getPixel($i,$j) ); + my $hsl = Convert::Color->new('rgb:'.join(',',map { $_ / 255 } @color))->convert_to('hsl'); + my $c = join(',',@color); + next if $hsl->lightness < 0.1; + $colors{$c} ||= { h => $hsl->hue, s => $hsl->saturation, l => $hsl->lightness, cnt => 0, c => $c}; + $colors{$c}->{cnt}++; + } + } + + for (values %colors) { + $_->{rank} = $_->{s} * $_->{cnt}; + } + my @top5 = grep { defined and $_->{'l'} and $_->{'c'} } + (sort { $b->{rank} <=> $a->{rank} } values %colors)[0..5]; + return \@top5; +}; + if (my $file_hash = _UploadedFile( 'logo-upload' )) { - my ($id, $msg) = RT->System->SetAttribute( Name => "UserLogo", - Description => "User-provided logo", - Content => { - type => $file_hash->{ContentType}, - data => $file_hash->{LargeContent}, - hash => md5_hex($file_hash->{LargeContent}), - } ); + $colors = $analyze_img->($file_hash->{LargeContent}); + + my $my_system = RT::System->new( $session{CurrentUser} ); + my ( $id, $msg ) = $my_system->SetAttribute( + Name => "UserLogo", + Description => "User-provided logo", + Content => { + type => $file_hash->{ContentType}, + data => $file_hash->{LargeContent}, + hash => md5_hex($file_hash->{LargeContent}), + colors => $colors, + }, + ); + push @results, loc("Unable to set UserLogo: [_1]", $msg) unless $id; $imgdata = $file_hash->{LargeContent}; @@ -227,6 +330,19 @@ else { my $content = $attr->Content; if (ref($content) eq 'HASH') { $imgdata = $content->{data}; + $colors = $content->{colors}; + unless ($colors) { + # No colors cached; attempt to generate them + $colors = $content->{colors} = $analyze_img->($content->{data}); + if ($content->{colors}) { + # Found colors; update the attribute + RT->System->SetAttribute( + Name => "UserLogo", + Description => "User-provided logo", + Content => $content, + ); + } + } } else { RT->System->DeleteAttribute('UserLogo'); @@ -256,63 +372,6 @@ if (!$user_css) { } @sections ); } - -# XXX: move this to some other modules - -use List::MoreUtils qw(uniq); - -my $has_color_analyzer = eval { require Convert::Color; 1 }; -my $colors; -my %gd_can; -my $valid_image_types; - -if (not RT->Config->Get('DisableGD') and $has_color_analyzer) { - require GD; - - # Always find out what GD can read... - for my $type (qw(Png Jpeg Gif)) { - $gd_can{$type}++ if GD::Image->can("newFrom${type}Data"); - } - $valid_image_types = join(", ", map { uc } sort { lc $a cmp lc $b } keys %gd_can); - - # ...but only analyze the image if we have data - if ($imgdata) { - if ( my $img = GD::Image->new($imgdata) ) { - $colors = analyze_img($img); - } - else { - # This has to be one damn long line because the loc() needs to be - # source parsed correctly. - push @results, loc("Automatically suggested theme colors aren't available for your image. This might be because you uploaded an image type that your installed version of GD doesn't support. Supported types are: [_1]. You can recompile libgd and GD.pm to include support for other image types.", $valid_image_types); - } - } -} - -sub analyze_img { - my $img = shift; - my $color; - - for my $i (0..$img->width-1) { - for my $j (0..$img->height-1) { - my @color = $img->rgb( $img->getPixel($i,$j) ); - my $hsl = Convert::Color->new('rgb:'.join(',',map { $_ / 255 } @color))->convert_to('hsl'); - my $c = join(',',@color); - next if $hsl->lightness < 0.1; - $color->{$c} ||= { h => $hsl->hue, s => $hsl->saturation, l => $hsl->lightness, cnt => 0, c => $c}; - $color->{$c}->{cnt}++; - } - } - - for (values %$color) { - $_->{rank} = $_->{s} * $_->{cnt}; - } - my @top5 = grep { defined and $_->{'l'} and $_->{'c'} } - (sort { $b->{rank} <=> $a->{rank} } values %$color)[0..5]; - if ((scalar uniq map {$_->{rank}} @top5) == 1) { - $RT::Logger->info("Only one color found in logo image"); - } - return \@top5; -} </%INIT> <%ARGS> $user_css => '' diff --git a/rt/share/html/Admin/Tools/index.html b/rt/share/html/Admin/Tools/index.html index 891fe000a..b80ed0a32 100644 --- a/rt/share/html/Admin/Tools/index.html +++ b/rt/share/html/Admin/Tools/index.html @@ -47,4 +47,4 @@ %# END BPS TAGGED BLOCK }}} <& /Admin/Elements/Header, Title => loc('System Tools') &> <& /Elements/Tabs &> -<& /Elements/ListMenu, menu => Menu()->child('tools')->child('config')->child('tools') &> +<& /Elements/ListMenu, menu => Menu()->child('admin')->child('tools') &> |