From 0c7f9a2952acf2caf16a2d1156f99d9c81b486b1 Mon Sep 17 00:00:00 2001 From: Mark Wells Date: Wed, 28 Mar 2012 14:00:45 -0700 Subject: fix location edit/tax district lookup interaction, #16757 --- httemplate/elements/city.html | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/httemplate/elements/city.html b/httemplate/elements/city.html index f6d2b4bad..6a2142f29 100644 --- a/httemplate/elements/city.html +++ b/httemplate/elements/city.html @@ -107,7 +107,11 @@ function <% $pre %>county_changed(what, callback) {} <% $text_style %> > -% if ( !$disable_select ) { +% if ( $disable_select ) { +%# avoid JS errors + +% } +% else { -

+
<% mt('Payment') |h %> <% ntable("#cccccc", 2) %> @@ -56,7 +56,29 @@ <% mt('Check #') |h %> -% } +% } +% elsif ( $payby eq 'CASH' and $conf->exists('require_cash_deposit_info') ) { + + <% mt('Bank') |h %> + + + + <% mt('Check #') |h %> + + + + <% mt('Teller #') |h %> + + + + <% mt('Depositor') |h %> + + + + <% mt('Account #') |h %> + + +% } % if ( $link eq 'custnum' || $link eq 'popup' ) { diff --git a/httemplate/edit/process/cust_pay.cgi b/httemplate/edit/process/cust_pay.cgi index e74f9022f..06f5e64d5 100755 --- a/httemplate/edit/process/cust_pay.cgi +++ b/httemplate/edit/process/cust_pay.cgi @@ -28,6 +28,8 @@ %} <%init> +my $conf = FS::Conf->new; + $cgi->param('linknum') =~ /^(\d+)$/ or die "Illegal linknum: ". $cgi->param('linknum'); my $linknum = $1; @@ -46,6 +48,7 @@ my $new = new FS::cust_pay ( { $_, scalar($cgi->param($_)); } qw( paid payby payinfo paybatch pkgnum discount_term + bank depositor account teller ) #} fields('cust_pay') } ); @@ -57,6 +60,6 @@ push @rights, 'Post cash payment' if $new->payby eq 'CASH'; die "access denied" unless $FS::CurrentUser::CurrentUser->access_right(\@rights); -my $error = $new->insert( 'manual' => 1 ); +my $error ||= $new->insert( 'manual' => 1 ); diff --git a/httemplate/view/cust_main/payment_history.html b/httemplate/view/cust_main/payment_history.html index b5b716199..c453ffadc 100644 --- a/httemplate/view/cust_main/payment_history.html +++ b/httemplate/view/cust_main/payment_history.html @@ -13,6 +13,7 @@ 'cust_main' => $cust_main, 'actionlabel' => emt('Enter check payment'), 'width' => 392, + 'height' => 392, &> % } @@ -24,6 +25,7 @@ 'cust_main' => $cust_main, 'actionlabel' => emt('Enter cash payment'), 'width' => 392, + 'height' => 392, &> % } diff --git a/httemplate/view/cust_pay.html b/httemplate/view/cust_pay.html index d02f1543d..f9c8bc19c 100644 --- a/httemplate/view/cust_pay.html +++ b/httemplate/view/cust_pay.html @@ -98,6 +98,28 @@ % } +% if ( $cust_pay->payby eq 'CASH' && $cust_pay->payinfo ) { + + <% mt('Bank') |h %> + <% $cust_pay->bank %> + + + + <% mt('Teller #') |h %> + <% $cust_pay->teller %> + + + + <% mt('Depositor') |h %> + <% $cust_pay->depositor %> + + + + <% mt('Account #') |h %> + <% $cust_pay->account %> + +% } + % if ( $conf->exists('pkg-balances') && $cust_pay->pkgnum ) { % my $cust_pkg = qsearchs('cust_pkg', { 'pkgnum' => $cust_pay->pkgnum } ); -- cgit v1.2.1 From fadc3d69d6a6bceac54fcb52b456222f28c42645 Mon Sep 17 00:00:00 2001 From: Mark Wells Date: Thu, 29 Mar 2012 17:12:00 -0700 Subject: one-line CSV format for invoice spool, #16382 --- FS/FS/Conf.pm | 4 ++-- FS/FS/cust_bill.pm | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/FS/FS/Conf.pm b/FS/FS/Conf.pm index 9c7710b22..1b01aa64a 100644 --- a/FS/FS/Conf.pm +++ b/FS/FS/Conf.pm @@ -2940,7 +2940,7 @@ and customer address. Include units.', 'section' => 'invoicing', 'description' => 'Enable FTP of raw invoice data - format.', 'type' => 'select', - 'select_enum' => [ '', 'default', 'billco', ], + 'select_enum' => [ '', 'default', 'oneline', 'billco', ], }, { @@ -2976,7 +2976,7 @@ and customer address. Include units.', 'section' => 'invoicing', 'description' => 'Enable spooling of raw invoice data - format.', 'type' => 'select', - 'select_enum' => [ '', 'default', 'billco', ], + 'select_enum' => [ '', 'default', 'oneline', 'billco', ], }, { diff --git a/FS/FS/cust_bill.pm b/FS/FS/cust_bill.pm index 3aa75eca5..945771e0d 100644 --- a/FS/FS/cust_bill.pm +++ b/FS/FS/cust_bill.pm @@ -2005,6 +2005,36 @@ sub print_csv { '0', # 29 | Other Taxes & Fees*** NUM* 9 ); + } elsif ( lc($opt{'format'}) eq 'oneline' ) { #name? + + my ($previous_balance) = $self->previous; + my $totaldue = sprintf('%.2f', $self->owed + $previous_balance); + my @items = map { + ($_->{pkgnum} || ''), + $_->{description}, + $_->{amount} + } $self->_items_pkg; + + $csv->combine( + $cust_main->agentnum, + $self->custnum, + $cust_main->first, + $cust_main->last, + $cust_main->address1, + $cust_main->address2, + $cust_main->city, + $cust_main->state, + $cust_main->zip, + + # invoice fields + time2str("%x", $self->_date), + $self->invnum, + $self->charged, + $totaldue, + + @items, + ); + } else { $csv->combine( @@ -2044,6 +2074,10 @@ sub print_csv { } + } elsif ( lc($opt{'format'}) eq 'oneline' ) { + + #do nothing + } else { foreach my $cust_bill_pkg ( $self->cust_bill_pkg ) { -- cgit v1.2.1 From c2ee6c5c4f274bbf86729cacd2fe011ea71f725d Mon Sep 17 00:00:00 2001 From: Mark Wells Date: Sat, 31 Mar 2012 17:56:52 -0700 Subject: add customer referrals to signup graph, #17050 --- FS/FS/Report/Table.pm | 21 ++++++++++++++++----- httemplate/graph/cust_signup.html | 29 +++++++++++++++++++---------- httemplate/graph/report_cust_signup.html | 6 ++++++ 3 files changed, 41 insertions(+), 15 deletions(-) diff --git a/FS/FS/Report/Table.pm b/FS/FS/Report/Table.pm index 3942543b5..b0e911f84 100644 --- a/FS/FS/Report/Table.pm +++ b/FS/FS/Report/Table.pm @@ -32,21 +32,32 @@ options in %opt. =over 4 -=item signups: The number of customers signed up. +=item signups: The number of customers signed up. Options are "refnum" +(limit by advertising source) and "indirect" (boolean, tells us to limit +to customers that have a referral_custnum that matches the advertising source). =cut sub signups { my( $self, $speriod, $eperiod, $agentnum, %opt ) = @_; - my @where = ( - $self->in_time_period_and_agent($speriod, $eperiod, $agentnum, 'signupdate') + my @where = ( $self->in_time_period_and_agent($speriod, $eperiod, $agentnum, + 'cust_main.signupdate') ); - if ( $opt{'refnum'} ) { + my $join = ''; + if ( $opt{'indirect'} ) { + $join = " JOIN cust_main AS referring_cust_main". + " ON (cust_main.referral_custnum = referring_cust_main.custnum)"; + + if ( $opt{'refnum'} ) { + push @where, "referring_cust_main.refnum = ".$opt{'refnum'}; + } + } + elsif ( $opt{'refnum'} ) { push @where, "refnum = ".$opt{'refnum'}; } $self->scalar_sql( - "SELECT COUNT(*) FROM cust_main WHERE ".join(' AND ', @where) + "SELECT COUNT(*) FROM cust_main $join WHERE ".join(' AND ', @where) ); } diff --git a/httemplate/graph/cust_signup.html b/httemplate/graph/cust_signup.html index dd9100f1e..a3eb702f2 100644 --- a/httemplate/graph/cust_signup.html +++ b/httemplate/graph/cust_signup.html @@ -9,7 +9,7 @@ 'agentnum' => $agentnum, 'sprintf' => '%u', 'disable_money' => 1, - 'bottom_total' => (scalar @items > 1 ? 1 : 0), + 'bottom_total' => (scalar @items > 1 && !$indirect ? 1 : 0), 'bottom_link' => $bottom_link, 'link_fromparam' => 'signupdate_begin', 'link_toparam' => 'signupdate_end', @@ -59,25 +59,34 @@ elsif ( $cgi->param('refnum') =~ /^(\d*)$/ ) { } } +my $indirect = ($cgi->param('indirect') eq 'Y' ? 1 : 0); + my (@items, @labels, @colors, @params, @links); my $hue = 0; -my $hue_increment = 125; +my $hue_increment = 75; my @signup_colors; foreach my $referral (@referral) { + my %params = ('refnum' => $referral->refnum) unless $all_referral; + push @items, 'signups'; push @labels, ( $all_referral ? 'Signups' : $referral->referral ); - push @params, ( $all_referral ? [] : [ 'refnum' => $referral->refnum ] ); + push @params, [ %params ]; push @links, $link . ($all_referral ? '' : "refnum=".$referral->refnum.';'); - if ( !@signup_colors ) { - @signup_colors = Color::Scheme->new - ->from_hue($hue) - ->scheme('analogic') - ->colors; - $hue += $hue_increment; + # rotate hue for each referral type + @signup_colors = Color::Scheme->new->from_hue($hue)->colors; + $hue += $hue_increment; + push @colors, $signup_colors[0]; + if ( $indirect ) { + push @items, 'signups'; + push @labels, $all_referral ? + 'Referrals' : + $referral->referral . ' referrals'; + push @params, [ %params, 'indirect' => 1 ]; + push @links, ''; + push @colors, $signup_colors[1]; } - push @colors, shift @signup_colors; } diff --git a/httemplate/graph/report_cust_signup.html b/httemplate/graph/report_cust_signup.html index 9d3f5006b..12dec8e6a 100644 --- a/httemplate/graph/report_cust_signup.html +++ b/httemplate/graph/report_cust_signup.html @@ -22,6 +22,12 @@ ) %> +<& /elements/tr-td-label.html, label => 'Show customer referrals' &> + + + + +
-- cgit v1.2.1 From 59db9d8aa66fe128a26e512c5172982e041c59ae Mon Sep 17 00:00:00 2001 From: Ivan Kohler Date: Sun, 1 Apr 2012 11:07:12 -0700 Subject: 3.0 --- httemplate/docs/about.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/httemplate/docs/about.html b/httemplate/docs/about.html index f0994e506..76a477c05 100644 --- a/httemplate/docs/about.html +++ b/httemplate/docs/about.html @@ -8,7 +8,7 @@
-© 2011 Freeside Internet Services, Inc.
+© 2012 Freeside Internet Services, Inc.
All rights reserved.
Licensed under the terms of the
GNU Affero General Public License.
@@ -29,7 +29,7 @@ GNU Affero General Public License.

-"The sky was yellow and the sun was blue" -R. Hunter +"A selfish heart is trouble, but a foolish heart is worse" -R. Hunter
<& /elements/tr-td-label.html, label => ($opt{'label'} || 'Router') &> @@ -27,7 +38,7 @@ function lock_ip_addr(obj, i) { records => \@routers, name_col => 'routername', value_col => 'routernum', - onchange => 'lock_ip_addr', + onchange => 'update_ip_addr', curr_value=> $opt{'routernum'}, }, { @@ -39,6 +50,7 @@ function lock_ip_addr(obj, i) { name_col => 'cidr', link_col => 'routernum', empty_label => '(any)', + onchange => 'update_ip_addr', curr_value => $opt{'blocknum'}, }, ] @@ -52,12 +64,11 @@ function lock_ip_addr(obj, i) { % } % else { + value="<% $opt{'ip_addr'} |h%>" onfocus="clearhint_ip_addr(this)"> % } - <%init> -- cgit v1.2.1 From b17ce7c641ad897ec35cac0c8f8e69320c19ab0e Mon Sep 17 00:00:00 2001 From: Ivan Kohler Date: Thu, 12 Apr 2012 15:13:49 -0700 Subject: adding quick package definition bulk change tool, RT#17348 --- bin/part_pkg-bulk_change | 72 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100755 bin/part_pkg-bulk_change diff --git a/bin/part_pkg-bulk_change b/bin/part_pkg-bulk_change new file mode 100755 index 000000000..aecfea580 --- /dev/null +++ b/bin/part_pkg-bulk_change @@ -0,0 +1,72 @@ +#!/usr/bin/perl + +use strict; +use vars qw( $opt_r $opt_o $opt_v ); +use Getopt::Std; +use FS::UID qw(adminsuidsetup); +use FS::Record qw(qsearch qsearchs); +use FS::part_pkg; +use FS::part_pkg_option; + +getopts('ro:v:'); + +my $user = shift or &usage; +adminsuidsetup $user; + +foreach my $part_pkg ( qsearch('part_pkg', {}) ) { + next if ! $part_pkg->freq && $opt_r; + + my %hash = ( + 'pkgpart' => $part_pkg->pkgpart, + 'optionname' => $opt_o, + ); + + my $part_pkg_option = qsearchs('part_pkg_option', \%hash); + + if ( $part_pkg_option ) { + next if $part_pkg_option->optionvalue eq $opt_v; + $part_pkg_option->optionvalue($opt_v); + my $error = $part_pkg_option->replace; + die $error if $error; + } else { + $part_pkg_option = new FS::part_pkg_option { %hash, 'optionvalue'=>$opt_v }; + my $error = $part_pkg_option->insert; + die $error if $error; + } + +} + +sub usage { + die "usage: part_pkg-bulk_change [ -r ] -o option_name -v option_value employee_username\n"; +} + +=head1 NAME + +cust_main-bulk_change + +=head1 SYNOPSIS + + part_pkg-bulk_change [ -r ] -o option_name -v option_value employee_username + +=head1 DESCRIPTION + +Command-line tool to change the payby field for a group of customers. + +-r: recurring package definitions only + +-o: part_pkg_option optionname + +-v: part_pkg_option optionvalue + +employee_username + +=head1 BUGS + +=head1 SEE ALSO + +L + +=cut + +1; + -- cgit v1.2.1 From c683be2e0bc89b9d11dfd5454a6cd21161b752ef Mon Sep 17 00:00:00 2001 From: Ivan Kohler Date: Thu, 12 Apr 2012 16:13:07 -0700 Subject: fix voiding of APPL and ANRD payments, RT#17344 --- FS/FS/cust_pay_void.pm | 30 ++---------------------------- 1 file changed, 2 insertions(+), 28 deletions(-) diff --git a/FS/FS/cust_pay_void.pm b/FS/FS/cust_pay_void.pm index f1193cd24..bebcfd4cc 100644 --- a/FS/FS/cust_pay_void.pm +++ b/FS/FS/cust_pay_void.pm @@ -68,9 +68,7 @@ order taker (see L) =item payby -`CARD' (credit cards), `CHEK' (electronic check/ACH), -`LECB' (phone bill billing), `BILL' (billing), `CASH' (cash), -`WEST' (Western Union), `MCRD' (Manual credit card), or `COMP' (free) +Payment Type (See L for valid values) =item payinfo @@ -186,6 +184,7 @@ sub check { || $self->ut_foreign_keyn('pkgnum', 'cust_pkg', 'pkgnum') || $self->ut_numbern('void_date') || $self->ut_textn('reason') + || $self->payinfo_check ; return $error if $error; @@ -197,31 +196,6 @@ sub check { $self->void_date(time) unless $self->void_date; - $self->payby =~ /^(CARD|CHEK|LECB|BILL|COMP|PREP|CASH|WEST|MCRD)$/ - or return "Illegal payby"; - $self->payby($1); - - #false laziness with cust_refund::check - if ( $self->payby eq 'CARD' ) { - my $payinfo = $self->payinfo; - $payinfo =~ s/\D//g; - $self->payinfo($payinfo); - if ( $self->payinfo ) { - $self->payinfo =~ /^(\d{13,16}|\d{8,9})$/ - or return "Illegal (mistyped?) credit card number (payinfo)"; - $self->payinfo($1); - validate($self->payinfo) or return "Illegal credit card number"; - return "Unknown card type" if $self->payinfo !~ /^99\d{14}$/ #token - && cardtype($self->payinfo) eq "Unknown"; - } else { - $self->payinfo('N/A'); - } - - } else { - $error = $self->ut_textn('payinfo'); - return $error if $error; - } - $self->void_usernum($FS::CurrentUser::CurrentUser->usernum) unless $self->void_usernum; -- cgit v1.2.1 From 3ccf7174fccb0b576a8c34838b3db4a429635483 Mon Sep 17 00:00:00 2001 From: Ivan Kohler Date: Thu, 12 Apr 2012 16:14:23 -0700 Subject: display apple and android store payments by name --- FS/FS/payby.pm | 5 +++++ httemplate/view/cust_main/payment_history.html | 8 +++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/FS/FS/payby.pm b/FS/FS/payby.pm index 33ed42507..d1961a58d 100644 --- a/FS/FS/payby.pm +++ b/FS/FS/payby.pm @@ -176,6 +176,11 @@ sub realtime { # can use realtime payment facilities return $hash{$payby}->{realtime}; } +sub payby2shortname { + my $self = shift; + map { $_ => $hash{$_}->{shortname} } $self->payby; +} + sub payby2longname { my $self = shift; map { $_ => $hash{$_}->{longname} } $self->payby; diff --git a/httemplate/view/cust_main/payment_history.html b/httemplate/view/cust_main/payment_history.html index c453ffadc..c7a7c8024 100644 --- a/httemplate/view/cust_main/payment_history.html +++ b/httemplate/view/cust_main/payment_history.html @@ -500,14 +500,15 @@ foreach my $cust_refund ($cust_main->cust_refund) { sub translate_payby { my ($payby,$payinfo) = (shift,shift); my %payby = ( + FS::payby->payby2shortname, BILL => $payinfo ? emt('Check #') : '', CHEK => emt('Electronic check '), PREP => emt('Prepaid card '), CARD => emt('Credit card #'), COMP => emt('Complimentary by '), - CASH => emt('Cash'), - WEST => emt('Western Union'), - MCRD => emt('Manual credit card'), + #CASH => emt('Cash'), + #WEST => emt('Western Union'), + #MCRD => emt('Manual credit card'), ); $payby = (exists $payby{$payby}) ? $payby{$payby} : $payby; $payby; @@ -516,6 +517,7 @@ sub translate_payby { sub translate_payby_refund { my ($payby,$payinfo) = (shift,shift); my %payby = ( + FS::payby->payby2shortname, BILL => $payinfo ? emt('Check #') : emt('Check'), CHEK => emt('Electronic check '), CARD => emt('Credit card #'), -- cgit v1.2.1 From 217bd576f8024ea541bdbb967e1c53f242980e61 Mon Sep 17 00:00:00 2001 From: Ivan Kohler Date: Thu, 12 Apr 2012 20:16:38 -0700 Subject: add cust_bill-line_item-date_description, RT#15858 --- FS/FS/Conf.pm | 14 ++++++++++++-- FS/FS/cust_bill.pm | 14 +++++++++++++- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/FS/FS/Conf.pm b/FS/FS/Conf.pm index d342e744d..80c034890 100644 --- a/FS/FS/Conf.pm +++ b/FS/FS/Conf.pm @@ -3602,9 +3602,19 @@ and customer address. Include units.', 'section' => 'billing', 'description' => 'Display format for line item date ranges on invoice line items.', 'type' => 'select', - 'select_hash' => [ '' => 'STARTDATE-ENDDATE', - 'month_of' => 'Month of MONTHNAME', + 'select_hash' => [ '' => 'STARTDATE-ENDDATE', + 'month_of' => 'Month of MONTHNAME', + 'X_month' => 'DATE_DESC MONTHNAME', ], + 'per_agent' => 1, + }, + + { + 'key' => 'cust_bill-line_item-date_description', + 'section' => 'billing', + 'description' => 'Text to display for "DATE_DESC" when using cust_bill-line_item-date_style DATE_DESC MONTHNAME.', + 'type' => 'text', + 'per_agent' => 1, }, { diff --git a/FS/FS/cust_bill.pm b/FS/FS/cust_bill.pm index 255ce6009..a76170a9b 100644 --- a/FS/FS/cust_bill.pm +++ b/FS/FS/cust_bill.pm @@ -4887,6 +4887,8 @@ sub _items_cust_bill_pkg { my $maxlength = $conf->config('cust_bill-latex_lineitem_maxlength') || 50; + my $cust_main = $self->cust_main;#for per-agent cust_bill-line_item-ate_style + my @b = (); my ($s, $r, $u) = ( undef, undef, undef ); foreach my $cust_bill_pkg ( @$cust_bill_pkgs ) @@ -5022,14 +5024,24 @@ sub _items_cust_bill_pkg { my $description = ($is_summary && $type && $type eq 'U') ? "Usage charges" : $desc; + #pry be a bit more efficient to look some of this conf stuff up + # outside the loop unless ( $conf->exists('disable_line_item_date_ranges') || $cust_pkg->part_pkg->option('disable_line_item_date_ranges',1) ) { my $time_period; - my $date_style = $conf->config('cust_bill-line_item-date_style'); + my $date_style = $conf->config( 'cust_bill-line_item-date_style', + $cust_main->agentnum + ); if ( defined($date_style) && $date_style eq 'month_of' ) { $time_period = time2str('The month of %B', $cust_bill_pkg->sdate); + } elsif ( defined($date_style) && $date_style eq 'X_month' ) { + my $desc = $conf->config( 'cust_bill-line_item-date_description', + $cust_main->agentnum + ); + $desc .= ' ' unless $desc =~ /\s$/; + $time_period = $desc. time2str('%B', $cust_bill_pkg->sdate); } else { $time_period = time2str($date_format, $cust_bill_pkg->sdate). " - ". time2str($date_format, $cust_bill_pkg->edate); -- cgit v1.2.1 From 18459c4369f63b7fda11a3ff7a0af067bed0c9bf Mon Sep 17 00:00:00 2001 From: Mark Wells Date: Fri, 13 Apr 2012 12:08:40 -0700 Subject: adjustment to display_custnum special format, #16815 --- FS/FS/Conf.pm | 3 ++- FS/FS/cust_main.pm | 11 +++++++++-- FS/FS/cust_main/Search.pm | 36 ++++++++++++++++++++---------------- 3 files changed, 31 insertions(+), 19 deletions(-) diff --git a/FS/FS/Conf.pm b/FS/FS/Conf.pm index 80c034890..edfe3c27a 100644 --- a/FS/FS/Conf.pm +++ b/FS/FS/Conf.pm @@ -3889,7 +3889,7 @@ and customer address. Include units.', 'section' => 'UI', 'description' => 'Prefix the customer number with this string for display purposes.', 'type' => 'text', - #and then probably agent-virt this to merge these instances + 'per_agent' => 1, }, { @@ -3898,6 +3898,7 @@ and customer address. Include units.', 'description' => 'Use this customer number prefix format', 'type' => 'select', 'select_hash' => [ '' => '', + 'CoStAg' => 'CoStAg (country, state, agent name or display_prefix)', 'CoStCl' => 'CoStCl (country, state, class name)' ], }, diff --git a/FS/FS/cust_main.pm b/FS/FS/cust_main.pm index 1e0e6d3b1..845d09848 100644 --- a/FS/FS/cust_main.pm +++ b/FS/FS/cust_main.pm @@ -3963,9 +3963,16 @@ cust_main-default_agent_custid is set and it has a value, custnum otherwise. sub display_custnum { my $self = shift; - my $prefix = $conf->config('cust_main-custnum-display_prefix') || ''; + my $prefix = $conf->config('cust_main-custnum-display_prefix', $self->agentnum) || ''; if ( my $special = $conf->config('cust_main-custnum-display_special') ) { - if ( $special eq 'CoStCl' ) { + if ( $special eq 'CoStAg' ) { + $prefix = uc( join('', + $self->country, + ($self->state =~ /^(..)/), + $prefix || ($self->agent->agent =~ /^(..)/) + ) ); + } + elsif ( $special eq 'CoStCl' ) { $prefix = uc( join('', $self->country, ($self->state =~ /^(..)/), diff --git a/FS/FS/cust_main/Search.pm b/FS/FS/cust_main/Search.pm index 62464e4aa..1e9eee79d 100644 --- a/FS/FS/cust_main/Search.pm +++ b/FS/FS/cust_main/Search.pm @@ -127,6 +127,12 @@ sub smart_search { || ( $conf->config('cust_main-agent_custid-format') eq 'ww?d+' && $search =~ /^\s*(\w\w?\d+)\s*$/ ) + || ( $conf->config('cust_main-custnum-display_special') + # it's not currently possible for special prefixes to contain + # digits, so just strip off any alphabetic prefix and match + # the rest to custnum + && $search =~ /^\s*[[:alpha:]]*(\d+)\s*$/ + ) || ( $conf->exists('address1-search' ) && $search =~ /^\s*(\d+\-?\w*)\s*$/ #i.e. 1234A or 9432-D ) @@ -143,25 +149,23 @@ sub smart_search { } ); } - #if this becomes agent-virt need to get a list of all prefixes the current - #user can see (via their agents) - my $prefix = $conf->config('cust_main-custnum-display_prefix'); - if ( $prefix && $prefix eq substr($num, 0, length($prefix)) ) { - push @cust_main, qsearch( { - 'table' => 'cust_main', - 'hashref' => { 'custnum' => 0 + substr($num, length($prefix)), - %options, + # for all agents this user can see, if any of them have custnum prefixes + # that match the search string, include customers that match the rest + # of the custnum and belong to that agent + foreach my $agentnum ( $FS::CurrentUser::CurrentUser->agentnums ) { + my $p = $conf->config('cust_main-custnum-display_prefix', $agentnum); + next if !$p; + if ( $p eq substr($num, 0, length($p)) ) { + push @cust_main, qsearch( { + 'table' => 'cust_main', + 'hashref' => { 'custnum' => 0 + substr($num, length($p)), + 'agentnum' => $agentnum, + %options, }, - 'extra_sql' => " AND $agentnums_sql", #agent virtualization - } ); + } ); + } } - push @cust_main, qsearch( { - 'table' => 'cust_main', - 'hashref' => { 'agent_custid' => $num, %options }, - 'extra_sql' => " AND $agentnums_sql", #agent virtualization - } ); - if ( $conf->exists('address1-search') ) { my $len = length($num); $num = lc($num); -- cgit v1.2.1 From 2c1bad9f29492546788aa4ffa0baf8e1dc0fff58 Mon Sep 17 00:00:00 2001 From: Ivan Kohler Date: Fri, 13 Apr 2012 18:35:24 -0700 Subject: style ticket tab --- httemplate/elements/freeside.css | 28 ++++++++++++++++++++++++++++ httemplate/elements/table-grid.html | 13 +------------ httemplate/view/cust_main.cgi | 4 ++-- httemplate/view/cust_main/tickets.html | 9 +++++---- 4 files changed, 36 insertions(+), 18 deletions(-) diff --git a/httemplate/elements/freeside.css b/httemplate/elements/freeside.css index 44a4a3ca2..c291e1e33 100644 --- a/httemplate/elements/freeside.css +++ b/httemplate/elements/freeside.css @@ -250,3 +250,31 @@ div.fstabcontainer { background-color:#f8f8f8; } +table.grid { + border: 1px solid #cccccc; + -moz-box-shadow: 1px 1px 2px #666666; + -webkit-box-shadow: 1px 1px 2px #666666; + box-shadow: 1px 1px 2px #666666; + filter: progid:DXImageTransform.Microsoft.Shadow(color='#666666', Direction=135, Strength=2); +} + +th.grid { + padding-left: 3px; + padding-right: 3px; + padding-bottom: 2px; + border: none; + empty-cells: show; +} + +td.grid { + padding-left: 3px; + padding-right: 3px; + padding-bottom: 2px; + border: none; + empty-cells: show; +} + +table.inv { border: none } +th.inv { border: none } +td.inv { border: none } + diff --git a/httemplate/elements/table-grid.html b/httemplate/elements/table-grid.html index 4d7deeaa4..4f4200570 100644 --- a/httemplate/elements/table-grid.html +++ b/httemplate/elements/table-grid.html @@ -1,15 +1,4 @@ - - - CELLPADDING=<% $opt{cellpadding} %> <% $opt{bgcolor} %> STYLE="border: 1px solid #cccccc;"> +
CELLPADDING=<% $opt{cellpadding} %> <% $opt{bgcolor} %>> <%init> diff --git a/httemplate/view/cust_main.cgi b/httemplate/view/cust_main.cgi index fda4db0d9..9ce55b0b9 100755 --- a/httemplate/view/cust_main.cgi +++ b/httemplate/view/cust_main.cgi @@ -232,9 +232,9 @@ function areyousure(href, message) { % } % if ( $view eq 'jumbo' ) { -

- <% mt('Tickets') |h %>
+
% } +
% if ( $view eq 'tickets' || $view eq 'jumbo' ) { diff --git a/httemplate/view/cust_main/tickets.html b/httemplate/view/cust_main/tickets.html index adfaead6e..194e90742 100644 --- a/httemplate/view/cust_main/tickets.html +++ b/httemplate/view/cust_main/tickets.html @@ -9,6 +9,7 @@ function updateTicketLink() { keys %new_param),'Queue=') %>" + selector.options[selector.selectedIndex].value; } +Tickets<% mt('Create new ticket') |h %> <% mt('in queue') |h %> %# fetch list of queues in which the user can create tickets @@ -28,12 +29,12 @@ function updateTicketLink() { % } + | +View +<% mt($openlabel) |h %> | +<% mt('resolved') |h %>
-(<% mt("View $openlabel tickets for this customer") |h %>) -(<% mt('View resolved tickets for this customer') |h %>) -

- <& /elements/table-grid.html &> % my $bgcolor1 = '#eeeeee'; % my $bgcolor2 = '#ffffff'; -- cgit v1.2.1 From 33013bb1ef0b5f07105fe13f5bfc06350fc4d868 Mon Sep 17 00:00:00 2001 From: Ivan Kohler Date: Fri, 13 Apr 2012 19:17:06 -0700 Subject: fix "Use of uninitialized valud $driver name in pattern match (m//) at /usr/local/share/perl/5.10.1/FS/part_event/Condition.pm" warnings, cust_bill_has_service and has_cust_tag conditions under MySQL, fallout from RT#17035 --- FS/FS/part_event/Condition.pm | 4 ++-- FS/FS/part_event/Condition/cust_bill_has_service.pm | 4 +--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/FS/FS/part_event/Condition.pm b/FS/FS/part_event/Condition.pm index b3948153e..fc69f1d0c 100644 --- a/FS/FS/part_event/Condition.pm +++ b/FS/FS/part_event/Condition.pm @@ -363,7 +363,7 @@ sub condition_sql_option_option { #used for part_event/Condition/cust_bill_has_service.pm and has_cust_tag.pm #a little false laziness w/above and condition_sql_option_integer sub condition_sql_option_option_integer { - my( $class, $option, $driver_name ) = @_; + my( $class, $option ) = @_; ( my $condname = $class ) =~ s/^.*:://; @@ -375,7 +375,7 @@ sub condition_sql_option_option_integer { AND part_event_condition_option.optionvalue = 'HASH' )"; - my $integer = ($driver_name =~ /^mysql/) ? 'UNSIGNED INTEGER' : 'INTEGER'; + my $integer = (driver_name =~ /^mysql/) ? 'UNSIGNED INTEGER' : 'INTEGER'; my $optionname = "CAST(optionname AS $integer)"; diff --git a/FS/FS/part_event/Condition/cust_bill_has_service.pm b/FS/FS/part_event/Condition/cust_bill_has_service.pm index 65c996437..6e981ee03 100644 --- a/FS/FS/part_event/Condition/cust_bill_has_service.pm +++ b/FS/FS/part_event/Condition/cust_bill_has_service.pm @@ -42,9 +42,7 @@ sub condition_sql { my( $class, $table, %opt ) = @_; my $servicenums = - $class->condition_sql_option_option_integer( 'has_service', - $opt{'driver_name'}, - ); + $class->condition_sql_option_option_integer('has_service'); my $sql = qq| 0 < ( SELECT COUNT(cs.svcpart) FROM cust_bill_pkg cbp, cust_svc cs -- cgit v1.2.1 From 401ba3ab0637de1bc460370949b75dca092375d8 Mon Sep 17 00:00:00 2001 From: Mark Wells Date: Sat, 14 Apr 2012 11:43:08 -0700 Subject: fix various quick payment entry problems, #17356 --- httemplate/elements/customer-table.html | 298 +++++++++++---------- httemplate/misc/batch-cust_pay.html | 24 +- httemplate/misc/process/batch-cust_pay.cgi | 2 +- .../misc/xmlhttp-cust_main-discount_terms.cgi | 19 +- httemplate/misc/xmlhttp-cust_main-search.cgi | 8 +- 5 files changed, 182 insertions(+), 169 deletions(-) diff --git a/httemplate/elements/customer-table.html b/httemplate/elements/customer-table.html index aa085c41a..a517ece2a 100644 --- a/httemplate/elements/customer-table.html +++ b/httemplate/elements/customer-table.html @@ -67,7 +67,45 @@ Example: this.value = ''; } - + + function update_customer(searchrow, customerArray) { + + var custnum_obj = document.getElementById('custnum'+searchrow); + var customer = document.getElementById('customer'+searchrow); + var customer_select = document.getElementById('cust_select'+searchrow); + + custnum_obj.disabled = false; + custnum_obj.style.backgroundColor = '#ffffff'; + customer.disabled = false; + customer.style.backgroundColor = '#ffffff'; + + if ( customerArray.length == 0 ) { + + custnum_obj.value = 'Not found'; + customer.value = 'Not found'; + custnum_obj.style.color = '#ff0000'; + customer.style.color = '#ff0000'; + + customer.style.display = ''; + customer_select.style.display = 'none'; + return false; + + } else if ( customerArray.length == 5 ) { + + custnum_obj.value = customerArray[0]; + custnum_obj.style.color = '#000000'; + customer.value = customerArray[1]; + + update_balance_text(searchrow, customerArray[2]); + update_status_text( searchrow, customerArray[3]); + update_status_color(searchrow, '#'+customerArray[4]); + + customer.style.display = ''; + customer_select.style.display = 'none'; + return true; + } + } + function <% $opt{prefix} %>search_invnum() { this.style.color = '#000000' @@ -99,55 +137,25 @@ Example: customer_select.style.display = 'none'; var custnum_obj = document.getElementById('custnum'+searchrow); - var balance = document.getElementById('balance'+searchrow); - var status = document.getElementById('status'+searchrow); - balance.innerHTML = ''; - status.innerHTML = ''; + update_balance_text(searchrow, ''); + update_status_text(searchrow, ''); + update_status_color(searchrow, '#000000'); function search_invnum_update(customers) { var customerArray = eval('(' + customers + ')'); - - custnum_obj.disabled = false; - custnum_obj.style.backgroundColor = '#ffffff'; - customer.disabled = false; - customer.style.backgroundColor = '#ffffff'; - - if ( customerArray.length == 0 ) { - - custnum_obj.value = 'Not found'; - customer.value = 'Not found'; - custnum_obj.style.color = '#ff0000'; - customer.style.color = '#ff0000'; - - customer.style.display = ''; - customer_select.style.display = 'none'; - - } else if ( customerArray.length == 5 ) { - - custnum_obj.value = customerArray[0]; - custnum_obj.style.color = '#000000'; - customer.value = customerArray[1]; - balance.innerHTML = '<% $money_char %>' + customerArray[2] + '   '; - status.innerHTML = customerArray[3]; - status.style.color = '#'+customerArray[4]; - - customer.style.display = ''; - customer_select.style.display = 'none'; + update_customer(searchrow, customerArray); % if ( $opt{invnum_update_callback} ) { <% $opt{invnum_update_callback} %>(searchrow, '<% $opt{prefix} %>') % } - } - } invnum_search( invnum, search_invnum_update ); } - function <% $opt{prefix} %>search_custnum() { this.style.color = '#000000' @@ -180,42 +188,19 @@ Example: var invnum = document.getElementById('invnum'+searchrow); invnum.value = ''; - - var balance = document.getElementById('balance'+searchrow); - balance.innerHTML = ''; - - var status = document.getElementById('status'+searchrow); - status.innerHTML = ''; - function search_custnum_update(customers) { - - var customerArray = eval('(' + customers + ')'); + update_balance_text(searchrow, ''); + update_status_text( searchrow, ''); + update_status_color(searchrow, '#000000'); - customer.disabled = false; - customer.style.backgroundColor = '#ffffff'; - - if ( customerArray.length == 0 ) { - - customer.value = 'Not found'; - customer.style.color = '#ff0000'; - custnum_obj.style.color = '#ff0000'; - - } else if ( customerArray.length == 5 ) { - - custnum_obj.value = customerArray[0]; - custnum_obj.style.color = '#000000'; - customer.value = customerArray[1]; - balance.innerHTML = '<% $money_char %>' + customerArray[2] + '   '; - status.innerHTML = customerArray[3]; - status.style.color = '#'+customerArray[4]; + function search_custnum_update(customers) { - customer.style.display = ''; - customer_select.style.display = 'none'; + var customerArray = eval('(' + customers + ')') || []; + update_customer(searchrow, customerArray); % if ( $opt{custnum_update_callback} ) { <% $opt{custnum_update_callback} %>(searchrow, '<% $opt{prefix} %>') % } - } } custnum_search(custnum, search_custnum_update ); @@ -251,39 +236,16 @@ Example: var customer_select = document.getElementById('cust_select'+searchrow); - var balance = document.getElementById('balance'+searchrow); - balance.innerHTML = ''; - - var status = document.getElementById('status'+searchrow); - status.innerHTML = ''; - function search_customer_update(customers) { - var customerArray = eval('(' + customers + ')'); + var customerArrayArray = eval('(' + customers + ')') || [ [] ]; custnum_obj.disabled = false; custnum_obj.style.backgroundColor = '#ffffff'; - if ( customerArray.length == 0 ) { - - custnum_obj.value = 'Not found'; - custnum_obj.style.color = '#ff0000'; - customer_obj.style.color = '#ff0000'; - - customer_obj.style.display = ''; - customer_select.style.display = 'none'; - - } else if ( customerArray.length == 1 ) { - - custnum_obj.value = customerArray[0][0]; - customer_obj.value = customerArray[0][1]; - balance.innerHTML = '<% $money_char %>' + customerArray[0][2] + '   '; - status.innerHTML = customerArray[0][3]; - status.style.color = '#'+customerArray[0][4]; - - customer_obj.style.display = ''; - customer_select.style.display = 'none'; + if ( customerArrayArray.length == 1 ) { + update_customer(customerArrayArray[1]); % if ( $opt{custnum_update_callback} ) { <% $opt{custnum_update_callback} %>(searchrow, '<% $opt{prefix} %>') % } @@ -294,14 +256,16 @@ Example: custnum_obj.style.color = '#ff0000'; //blank the current list - for ( var i = customer_select.length; i >= 0; i-- ) - customer_select.options[i] = null; + customer_select.options.length = 0; opt(customer_select, '', 'Multiple customers match "' + customer + '" - select one', '#ff0000'); - //add the multiple customers - for ( var s = 0; s < customerArray.length; s++ ) - opt(customer_select, customerArray[s][0] + '_' + customerArray[s][2] + '_' + customerArray[s][3] + '_' + customerArray[s][4], customerArray[s][1], '#000000'); + for ( var s = 0; s < customerArrayArray.length; s++ ) { + opt(customer_select, + JSON.stringify(customerArrayArray[s]), + customerArrayArray[s][1], + '#000000'); + } opt(customer_select, 'cancel', '(Edit search string)', '#000000'); @@ -341,27 +305,7 @@ Example: } else { - var pos_underscore1 = custnum_balance_status.indexOf('_'); - var pos_underscore2 = custnum_balance_status.indexOf('_',pos_underscore1+1); - var pos_underscore3 = custnum_balance_status.indexOf('_',pos_underscore2+1); - var custnum = custnum_balance_status.substring(0,pos_underscore1); - var balance = custnum_balance_status.substring(pos_underscore1+1,pos_underscore2) + '   '; - var status = custnum_balance_status.substring(pos_underscore2+1,pos_underscore3); - var color = custnum_balance_status.substring(pos_underscore3+1); - - custnum_obj.value = custnum; - custnum_obj.style.color = '#000000'; - - customer_obj.value = customer; - customer_obj.style.color = '#000000'; - - balance_obj.innerHTML = '<% $money_char %>' + balance; - - status_obj.innerHTML = status; - status_obj.style.color = '#'+color; - - this.style.display = 'none'; - customer_obj.style.display = ''; + update_customer(searchrow, JSON.parse(custnum_balance_status)); % if ( $opt{custnum_update_callback} ) { <% $opt{custnum_update_callback} %>(searchrow, '<% $opt{prefix} %>') @@ -378,6 +322,23 @@ Example: what.options[length] = optionName; } + function update_status_text(rownum, newval) { + document.getElementById('status'+rownum).value = newval; + document.getElementById('status'+rownum+'_text').innerHTML = newval; + } + + function update_status_color(rownum, newval) { + document.getElementById('statuscolor'+rownum).value = newval; + document.getElementById('status'+rownum+'_text').style.color = newval; + } + + function update_balance_text(rownum, newval) { + document.getElementById('balance'+rownum).value = newval; + document.getElementById('balance'+rownum+'_text').innerHTML = newval; + } + + +
@@ -430,14 +391,26 @@ Example: - + + % my $col = 0; % foreach my $field ( @{$opt{fields}} ) { % my $value; @@ -494,15 +482,6 @@ Example: % $col++; % } - % } @@ -613,15 +592,28 @@ Example: row.appendChild(custnum_cell); var status_cell = document.createElement('TD'); + status_cell.style.textAlign = 'center'; - var status_span = document.createElement('SPAN'); - status_span.setAttribute('name', 'status'+<% $opt{prefix} %>rownum); - status_span.setAttribute('id', 'status'+<% $opt{prefix} %>rownum); - status_span.style.textAlign = 'center'; - status_span.style.fontWeight = 'bold'; - status_span.setAttribute('rownum', <% $opt{prefix} %>rownum); - status_cell.appendChild(status_span); + var status_span = document.createElement('SPAN'); + status_span.setAttribute('id', 'status'+<% $opt{prefix} %>rownum+'_text'); + status_span.style.fontWeight = 'bold'; + status_span.setAttribute('rownum', <% $opt{prefix} %>rownum); + status_cell.appendChild(status_span); + var status_input = document.createElement('INPUT'); + status_input.setAttribute('type', 'hidden'); + status_input.setAttribute('name', 'status'+<% $opt{prefix} %>rownum); + status_input.setAttribute('id', 'status'+<% $opt{prefix} %>rownum); + status_input.setAttribute('rownum', <% $opt{prefix} %>rownum); + status_cell.appendChild(status_input); + + var statuscolor_input = document.createElement('INPUT'); + statuscolor_input.setAttribute('type', 'hidden'); + statuscolor_input.setAttribute('name', 'statuscolor'+<% $opt{prefix} %>rownum); + statuscolor_input.setAttribute('id', 'statuscolor'+<% $opt{prefix} %>rownum); + statuscolor_input.setAttribute('rownum', <% $opt{prefix} %>rownum); + status_cell.appendChild(statuscolor_input); + row.appendChild(status_cell); var customer_cell = document.createElement('TD'); @@ -649,13 +641,25 @@ Example: row.appendChild(customer_cell); var balance_cell = document.createElement('TD'); - balance_cell.style.textAlign = 'right'; - - var balance_span = document.createElement('SPAN'); - balance_span.setAttribute('name', 'balance'+<% $opt{prefix} %>rownum); - balance_span.setAttribute('id', 'balance'+<% $opt{prefix} %>rownum); - balance_span.setAttribute('rownum', <% $opt{prefix} %>rownum); - balance_cell.appendChild(balance_span); + + balance_cell.style.textAlign = 'right'; + balance_cell.appendChild(document.createTextNode('<%$money_char%>')); + + var balance_span = document.createElement('SPAN'); + balance_span.setAttribute('id', 'balance'+<% $opt{prefix} %>rownum+'_text'); + balance_span.setAttribute('rownum', <% $opt{prefix} %>rownum); + balance_cell.appendChild(balance_span); + + balance_cell.appendChild( + document.createTextNode(String.fromCharCode(160)) //  + ); + + var balance_input = document.createElement('INPUT'); + balance_input.setAttribute('type', 'hidden'); + balance_input.setAttribute('name', 'balance'+<% $opt{prefix} %>rownum); + balance_input.setAttribute('id', 'balance'+<% $opt{prefix} %>rownum); + balance_input.setAttribute('rownum', <% $opt{prefix} %>rownum); + balance_cell.appendChild(balance_input); row.appendChild(balance_cell); @@ -676,9 +680,10 @@ Example: my_cell.appendChild(my_text); % } +% my $name = (ref($field) eq 'CODE') ? "column${col}_" : $field; var my_input = document.createElement('INPUT'); - my_input.setAttribute('name', '<% $field %>'+<% $opt{prefix} %>rownum); - my_input.setAttribute('id', '<% $field %>'+<% $opt{prefix} %>rownum); + my_input.setAttribute('name', '<% $name %>'+<% $opt{prefix} %>rownum); + my_input.setAttribute('id', '<% $name %>'+<% $opt{prefix} %>rownum); my_input.style.textAlign = '<% $align{ $opt{align}->[$col] || 'l' } %>'; my_input.setAttribute('size', <% $sizes->[$col] || 10 %>); % if ($types->[$col] eq 'immutable') { @@ -725,7 +730,7 @@ my $conf = new FS::Conf; $opt{prefix} = '' unless defined $opt{prefix}; $opt{prefix} .= '_' if $opt{prefix}; -my $types = $opt{'types'} ? [ @{$opt{'types'}} ] : []; +my $types = $opt{'type'} ? [ @{$opt{'type'}} ] : []; my $sizes = $opt{'size'} ? [ @{$opt{'size'}} ] : []; my $param = $opt{param}; @@ -742,5 +747,4 @@ my %align = ( ); my $money_char = $conf->config('money_char') || '$'; - diff --git a/httemplate/misc/batch-cust_pay.html b/httemplate/misc/batch-cust_pay.html index 11fdeee61..2e798652d 100644 --- a/httemplate/misc/batch-cust_pay.html +++ b/httemplate/misc/batch-cust_pay.html @@ -62,10 +62,10 @@ function select_discount_term(row, prefix) { name_singular => 'payment', header => \@header, fields => \@fields, - types => \@types, + type => \@types, align => \@align, - sizes => \@sizes, - colors => \@colors, + size => \@sizes, + color => \@colors, param => \%param, footer => \@footer, footer_align => \@footer_align, @@ -96,18 +96,19 @@ die "access denied" my $conf = new FS::Conf; my $money_char = $conf->config('money_char') || '$'; -my @header = ( '', 'Amount', 'Check #' ); -my @fields = ( sub { "$money_char" }, 'paid', 'payinfo' ); -my @types = ( 'immutable', '', '' ); -my @align = ( 'c', 'r', 'r' ); -my @sizes = ( 0, 8, 10 ); -my @colors = ( '', '', '' ); +my @header = ( 'Amount', 'Check #' ); +my @fields = ( 'paid', 'payinfo' ); +my @types = ( '', '' ); +my @align = ( 'r', 'r' ); +my @sizes = ( 8, 10 ); +my @colors = ( '', '' ); my %param = (); -my @footer = ( "$money_char", '_TOTAL', '' ); -my @footer_align = ( 'c', 'r', 'r' ); +my @footer = ( '_TOTAL', '' ); +my @footer_align = ( 'r', 'r' ); my $custnum_update_callback = ''; if ( FS::Record->scalar_sql('SELECT COUNT(*) FROM part_pkg_discount') ) { + #push @header, 'Discount'; push @header, ''; push @fields, 'discount_term'; push @types, 'immutable'; @@ -119,6 +120,7 @@ if ( FS::Record->scalar_sql('SELECT COUNT(*) FROM part_pkg_discount') ) { $custnum_update_callback = 'select_discount_term'; } +#push @header, 'Error'; push @header, ''; push @fields, 'error'; push @types, 'immutable'; diff --git a/httemplate/misc/process/batch-cust_pay.cgi b/httemplate/misc/process/batch-cust_pay.cgi index aa371266c..a6b90ea74 100644 --- a/httemplate/misc/process/batch-cust_pay.cgi +++ b/httemplate/misc/process/batch-cust_pay.cgi @@ -19,7 +19,7 @@ % 'extra_sql' => ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql, % }); % } -% if ( !$cust_main ) { # not found, try agent_custid +% if ( length($custnum) and !$cust_main ) { # not found, try agent_custid % $cust_main = qsearchs({ % 'table' => 'cust_main', % 'hashref' => { 'agent_custid' => $custnum }, diff --git a/httemplate/misc/xmlhttp-cust_main-discount_terms.cgi b/httemplate/misc/xmlhttp-cust_main-discount_terms.cgi index 71e2da597..b524e69fc 100644 --- a/httemplate/misc/xmlhttp-cust_main-discount_terms.cgi +++ b/httemplate/misc/xmlhttp-cust_main-discount_terms.cgi @@ -2,15 +2,18 @@ % % my $return = []; % my $custnum = $cgi->param('arg'); -% my $cust_main = ''; -% $cust_main = qsearchs({ -% 'table' => 'cust_main', -% 'hashref' => { 'custnum' => $custnum }, -% 'extra_sql' => ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql, -% }); +% if ( $custnum =~ /^\d+$/ ) { +% my $cust_main = ''; +% $cust_main = qsearchs({ +% 'table' => 'cust_main', +% 'hashref' => { 'custnum' => $custnum }, +% 'extra_sql' => ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql, +% }); % -% if ($cust_main) { -% $return = [ map [ $_, "$_ months" ], $cust_main->discount_terms ]; +% if ($cust_main) { +% $return = [ map [ $_, sprintf("%d months", $_) ], +% $cust_main->discount_terms ]; +% } % } % <% objToJson($return) %> diff --git a/httemplate/misc/xmlhttp-cust_main-search.cgi b/httemplate/misc/xmlhttp-cust_main-search.cgi index 68c5bf597..436501e8b 100644 --- a/httemplate/misc/xmlhttp-cust_main-search.cgi +++ b/httemplate/misc/xmlhttp-cust_main-search.cgi @@ -18,9 +18,13 @@ % } elsif ( $sub eq 'invnum_search' ) { % % my $string = $cgi->param('arg'); -% my $inv = qsearchs('cust_bill', { 'invnum' => $string }); -% my $return = $inv ? findbycustnum($inv->custnum,0) : []; +% if ( $string =~ /^(\d+)$/ ) { +% my $inv = qsearchs('cust_bill', { 'invnum' => $1 }); +% my $return = $inv ? findbycustnum($inv->custnum,0) : []; <% objToJson($return) %> +% } else { #return nothing +[] +% } % } % elsif ( $sub eq 'exact_search' ) { % # XXX possibly should query each element separately -- cgit v1.2.1 From 2ce6ee8e5cd817a4018ad26eb1e364198c1dd931 Mon Sep 17 00:00:00 2001 From: Ivan Kohler Date: Sun, 15 Apr 2012 15:38:27 -0700 Subject: add cust_class-tax_exempt conf setting to control the tax exemption flag per customer class rather than per indivual customer, RT#16818 --- FS/FS/Conf.pm | 6 ++++++ FS/FS/Schema.pm | 9 +++++---- FS/FS/cust_class.pm | 15 +++++++++++++++ FS/FS/cust_main/Billing.pm | 8 ++++++-- httemplate/edit/cust_class.html | 23 +++++++++++++++++++++-- httemplate/edit/cust_main/billing.html | 14 +++++++++++--- httemplate/edit/elements/class_Common.html | 4 ++-- httemplate/edit/pkg_class.html | 2 +- httemplate/view/cust_main/billing.html | 20 ++++++++++++-------- 9 files changed, 79 insertions(+), 22 deletions(-) diff --git a/FS/FS/Conf.pm b/FS/FS/Conf.pm index edfe3c27a..81443632c 100644 --- a/FS/FS/Conf.pm +++ b/FS/FS/Conf.pm @@ -4909,6 +4909,12 @@ and customer address. Include units.', 'type' => 'select-agent', }, + { + 'key' => 'cust_class-tax_exempt', + 'section' => 'billing', + 'description' => 'Control the tax exemption flag per customer class rather than per indivual customer.', + 'type' => 'checkbox', + }, { key => "apacheroot", section => "deprecated", description => "DEPRECATED", type => "text" }, { key => "apachemachine", section => "deprecated", description => "DEPRECATED", type => "text" }, diff --git a/FS/FS/Schema.pm b/FS/FS/Schema.pm index 5b8525c04..3894f65f8 100644 --- a/FS/FS/Schema.pm +++ b/FS/FS/Schema.pm @@ -1130,10 +1130,11 @@ sub tables_hashref { 'cust_class' => { 'columns' => [ - 'classnum', 'serial', '', '', '', '', - 'classname', 'varchar', '', $char_d, '', '', - 'categorynum', 'int', 'NULL', '', '', '', - 'disabled', 'char', 'NULL', 1, '', '', + 'classnum', 'serial', '', '', '', '', + 'classname', 'varchar', '', $char_d, '', '', + 'categorynum', 'int', 'NULL', '', '', '', + 'tax', 'char', 'NULL', 1, '', '', + 'disabled', 'char', 'NULL', 1, '', '', ], 'primary_key' => 'classnum', 'unique' => [], diff --git a/FS/FS/cust_class.pm b/FS/FS/cust_class.pm index a811be7a7..7cbc9b818 100644 --- a/FS/FS/cust_class.pm +++ b/FS/FS/cust_class.pm @@ -44,6 +44,11 @@ Text name of this customer class Number of associated cust_category (see L) +=item tax + +Tax exempt flag, empty or 'Y'. Used when the cust_class-tax_exempt +configuration setting is turned on. + =item disabled Disabled flag, empty or 'Y' @@ -86,6 +91,16 @@ Checks all fields to make sure this is a valid customer class. If there is an error, returns the error, otherwise returns false. Called by the insert and replace methods. +=cut + +sub check { + my $self = shift; + + $self->ut_enum('tax', [ '', 'Y' ]) + || $self->SUPER::check; + +} + =item cust_category =item category diff --git a/FS/FS/cust_main/Billing.pm b/FS/FS/cust_main/Billing.pm index 0a557fca2..ca8d9960c 100644 --- a/FS/FS/cust_main/Billing.pm +++ b/FS/FS/cust_main/Billing.pm @@ -877,7 +877,7 @@ sub _make_lines { my $part_pkg = $params{part_pkg} or die "no part_pkg specified"; my $cust_pkg = $params{cust_pkg} or die "no cust_pkg specified"; - my $precommit_hooks = $params{precommit_hooks} or die "no package specified"; + my $precommit_hooks = $params{precommit_hooks} or die "no precommit_hooks specified"; my $cust_bill_pkgs = $params{line_items} or die "no line buffer specified"; my $total_setup = $params{setup} or die "no setup accumulator specified"; my $total_recur = $params{recur} or die "no recur accumulator specified"; @@ -1178,7 +1178,11 @@ sub _handle_taxes { push @classes, 'setup' if ($cust_bill_pkg->setup && !$options->{cancel}); push @classes, 'recur' if ($cust_bill_pkg->recur && !$options->{cancel}); - if ( $self->tax !~ /Y/i && $self->payby ne 'COMP' ) { + my $exempt = $conf->exists('cust_class-tax_exempt') + ? ( $self->cust_class ? $self->cust_class->tax : '' ) + : $self->tax; + + if ( $exempt !~ /Y/i && $self->payby ne 'COMP' ) { if ( $conf->exists('enable_taxproducts') && ( scalar($part_pkg->part_pkg_taxoverride) diff --git a/httemplate/edit/cust_class.html b/httemplate/edit/cust_class.html index fdb58e687..8fce90588 100644 --- a/httemplate/edit/cust_class.html +++ b/httemplate/edit/cust_class.html @@ -1,5 +1,24 @@ <% include( 'elements/class_Common.html', - 'name' => 'Customer Class', - 'table' => 'cust_class', + 'name' => 'Customer Class', + 'table' => 'cust_class', + 'addl_fields' => \@addl_fields, + 'addl_labels' => { 'tax' => 'Tax Exempt' }, ) %> +<%init> + +my $conf = new FS::Conf; + +my @addl_fields = (); +if ( $conf->exists('cust_class-tax_exempt') ) { + push @addl_fields, { 'field' => 'tax', + 'type' => 'checkbox', + 'value' => 'Y', + }; +} else { + push @addl_fields, { 'field' => 'tax', + 'type' => 'hidden', + }; +} + + diff --git a/httemplate/edit/cust_main/billing.html b/httemplate/edit/cust_main/billing.html index 18c7ae9a6..9f4cb74cd 100644 --- a/httemplate/edit/cust_main/billing.html +++ b/httemplate/edit/cust_main/billing.html @@ -437,9 +437,17 @@ % my @exempt_groups = grep /\S/, $conf->config('tax-cust_exempt-groups'); - - - +% if ( $conf->exists('cust_class-tax_exempt') ) { + + + +% } else { + + + + + +% } % foreach my $exempt_group ( @exempt_groups ) { % #escape $exempt_group for NAME diff --git a/httemplate/edit/elements/class_Common.html b/httemplate/edit/elements/class_Common.html index 69da4db31..a0025b31f 100644 --- a/httemplate/edit/elements/class_Common.html +++ b/httemplate/edit/elements/class_Common.html @@ -34,9 +34,9 @@ my $fields = [ 'classname', ), { field=>'disabled', type=>'checkbox', value=>'Y', }, ]; -push @$fields, $opt{'addl_fields'} if $opt{'addl_fields'}; +push @$fields, @{ $opt{'addl_fields'} } if $opt{'addl_fields'}; my %addl_labels = (); -%addl_labels = %{$opt{'addl_labels'}} if $opt{'addl_labels'}; +%addl_labels = %{ $opt{'addl_labels'} } if $opt{'addl_labels'}; diff --git a/httemplate/edit/pkg_class.html b/httemplate/edit/pkg_class.html index 1bc100e36..c4e3d8ac5 100644 --- a/httemplate/edit/pkg_class.html +++ b/httemplate/edit/pkg_class.html @@ -10,7 +10,7 @@ my $conf = new FS::Conf; my %opt = (); if($conf->exists('cust_main-require_censustract')) { - $opt{'addl_fields'} = qw( fcc_ds0s ); + $opt{'addl_fields'} = [ 'fcc_ds0s' ]; $opt{'addl_labels'} = { 'fcc_ds0s' => 'FCC form 477 voice-grade equivalents' }; } diff --git a/httemplate/view/cust_main/billing.html b/httemplate/view/cust_main/billing.html index 522c6db86..4d55f7002 100644 --- a/httemplate/view/cust_main/billing.html +++ b/httemplate/view/cust_main/billing.html @@ -189,15 +189,19 @@ % my $no = emt('no'); % my @exempt_groups = grep /\S/, $conf->config('tax-cust_exempt-groups'); - - - - + +% unless ( $conf->exists('cust_class-tax_exempt') ) { + + + + +% } + % foreach my $exempt_group ( @exempt_groups ) { - - - - + + + + % } % if ( $conf->exists('enable_taxproducts') ) { -- cgit v1.2.1 From d09facc6cc8c60cc3e82c656c827a25a6995b3eb Mon Sep 17 00:00:00 2001 From: Ivan Kohler Date: Sun, 15 Apr 2012 15:44:20 -0700 Subject: add cust_class-tax_exempt conf setting to control the tax exemption flag per customer class rather than per indivual customer, RT#16818 --- httemplate/browse/cust_class.html | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/httemplate/browse/cust_class.html b/httemplate/browse/cust_class.html index d7c622837..70a279a05 100644 --- a/httemplate/browse/cust_class.html +++ b/httemplate/browse/cust_class.html @@ -42,4 +42,11 @@ if ($sth->fetchrow_arrayref->[0]) { push @$links, $link; } +my $conf = new FS::Conf; +if ( $conf->exists('cust_class-tax_exempt') ) { + push @$header, 'Tax exempt'; + push @$fields, 'tax'; + push @$links, ''; +} + -- cgit v1.2.1 From 9d97b3c2da538eb34c2ec609dd638241fd04d2a8 Mon Sep 17 00:00:00 2001 From: Ivan Kohler Date: Sun, 15 Apr 2012 17:49:39 -0700 Subject: add an $import global flag to cust_location so we can avoid geocoding on batch import, RT#16400 --- FS/FS/cust_location.pm | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/FS/FS/cust_location.pm b/FS/FS/cust_location.pm index f863b1020..a5250ec05 100644 --- a/FS/FS/cust_location.pm +++ b/FS/FS/cust_location.pm @@ -1,7 +1,8 @@ package FS::cust_location; +use base qw( FS::geocode_Mixin FS::Record ); use strict; -use base qw( FS::geocode_Mixin FS::Record ); +use vars qw( $import ); use Locale::Country; use FS::UID qw( dbh ); use FS::Record qw( qsearch ); #qsearchs ); @@ -10,6 +11,8 @@ use FS::prospect_main; use FS::cust_main; use FS::cust_main_county; +$import = 0; + =head1 NAME FS::cust_location - Object methods for cust_location records @@ -195,7 +198,7 @@ sub check { return $error if $error; $self->set_coord - unless $self->latitude && $self->longitude; + unless $import || ($self->latitude && $self->longitude); return "No prospect or customer!" unless $self->prospectnum || $self->custnum; return "Prospect and customer!" if $self->prospectnum && $self->custnum; -- cgit v1.2.1 From 6f01c7cd5ed2945e9a999d8dd0ec5f27a26358b0 Mon Sep 17 00:00:00 2001 From: Ivan Kohler Date: Mon, 16 Apr 2012 11:53:33 -0700 Subject: fix disabled events showing up in billing event clone dropdown --- httemplate/browse/part_event.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/httemplate/browse/part_event.html b/httemplate/browse/part_event.html index 03996435e..c06a14fe7 100644 --- a/httemplate/browse/part_event.html +++ b/httemplate/browse/part_event.html @@ -174,7 +174,7 @@ my $html_init = qq!Add a new event!. ' or !; my @values = split '\s+', $value if $multi; my @options; -- cgit v1.2.1 From 1c59bba12621e154765a8255534e94a041dfd200 Mon Sep 17 00:00:00 2001 From: Mark Wells Date: Tue, 17 Apr 2012 15:52:14 -0700 Subject: link tickets to services, #17067 --- FS/FS/TicketSystem/RT_External.pm | 51 +++++-- FS/FS/TicketSystem/RT_Internal.pm | 63 +++++++- FS/FS/cust_svc.pm | 86 +++++++++++ FS/FS/svc_phone.pm | 3 +- httemplate/elements/form-create_ticket.html | 38 +++++ httemplate/elements/table-tickets.html | 159 ++++++++++++++++++++ httemplate/view/cust_main/tickets.html | 166 +-------------------- httemplate/view/elements/svc_Common.html | 4 + httemplate/view/svc_acct.cgi | 4 + httemplate/view/svc_domain.cgi | 4 + httemplate/view/svc_external.cgi | 5 + httemplate/view/svc_forward.cgi | 4 + httemplate/view/svc_www.cgi | 4 + rt/lib/RT/Interface/Web_Vendor.pm | 26 +++- rt/lib/RT/Record.pm | 47 +++++- rt/lib/RT/Tickets_Overlay.pm | 182 ++++++++++++++++++----- rt/lib/RT/URI/freeside/Internal.pm | 81 +++++++++- rt/share/html/Elements/CustomerFields | 16 +- rt/share/html/Elements/RT__Ticket/ColumnMap | 1 + rt/share/html/Elements/ServiceFields | 161 ++++++++++++++++++++ rt/share/html/Search/Elements/BuildFormatString | 1 + rt/share/html/Search/Elements/PickBasics | 1 - rt/share/html/Search/Elements/PickCriteria | 1 + rt/share/html/Search/Elements/PickCustomerFields | 8 + rt/share/html/Ticket/Elements/AddCustomers | 37 ++++- rt/share/html/Ticket/Elements/EditCustomers | 45 +++--- rt/share/html/Ticket/Elements/ShowCustomers | 17 +-- 27 files changed, 934 insertions(+), 281 deletions(-) create mode 100644 httemplate/elements/form-create_ticket.html create mode 100644 httemplate/elements/table-tickets.html create mode 100644 rt/share/html/Elements/ServiceFields create mode 100644 rt/share/html/Search/Elements/PickCustomerFields diff --git a/FS/FS/TicketSystem/RT_External.pm b/FS/FS/TicketSystem/RT_External.pm index f976ac0e3..22d2472ef 100644 --- a/FS/FS/TicketSystem/RT_External.pm +++ b/FS/FS/TicketSystem/RT_External.pm @@ -97,6 +97,11 @@ sub customer_tickets { } +sub service_tickets { + warn "service_tickets not available with RT_External.\n"; + return; +} + sub comments_on_tickets { my ($self, $custnum, $limit, $time ) = @_; $limit ||= 0; @@ -206,7 +211,20 @@ sub statuses { } sub href_customer_tickets { - my( $self, $custnum ) = ( shift, shift ); + my($self, $custnum) = (shift, shift); + if ( $custnum =~ /^(\d+)$/ ) { + return $self->href_search_tickets("MemberOf = 'freeside://freeside/cust_main/$1'"); + } + warn "bad custnum $custnum"; return ''; +} + +sub href_service_tickets { + warn "service_tickets not available with RT_External.\n"; + ''; +} + +sub href_search_tickets { + my( $self, $where ) = ( shift, shift ); my( $priority, @statuses); if ( ref($_[0]) ) { my $opt = shift; @@ -225,8 +243,8 @@ sub href_customer_tickets { #$href .= my $href = "Search/Results.html?Order=ASC&". - "Query= MemberOf = 'freeside://freeside/cust_main/$custnum' ". - #" AND ( Status = 'open' OR Status = 'new' OR Status = 'stalled' )" + "Query= $where" . + #MemberOf = 'freeside://freeside/cust_main/$custnum' ". " AND ( ". join(' OR ', map "Status = '$_'", @statuses ). " ) " ; @@ -274,15 +292,19 @@ sub href_customer_tickets { } sub href_params_new_ticket { - my( $self, $custnum_or_cust_main, $requestors ) = @_; - - my( $custnum, $cust_main ); - if ( ref($custnum_or_cust_main) ) { - $cust_main = $custnum_or_cust_main; - $custnum = $cust_main->custnum; - } else { - $custnum = $custnum_or_cust_main; - $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } ); + # my( $self, $custnum_or_cust_main, $requestors ) = @_; + # no longer takes $custnum--it must be an object + my ( $self, $object, $requestors ) = @_; + my $cust_main; # for default requestors + if ( $object->isa('FS::cust_main') ) { + $cust_main = $object; + } + elsif ( $object->isa('FS::svc_Common') ) { + $object = $object->cust_svc; + $cust_main = $object->cust_pkg->cust_main if ( $object->cust_pkg ); + } + elsif ( $object->isa('FS::cust_svc') ) { + $cust_main = $object->cust_pkg->cust_main if ( $object->cust_pkg ); } # explicit $requestors > config option > invoicing_list @@ -291,9 +313,12 @@ sub href_params_new_ticket { $requestors = $cust_main->invoicing_list_emailonly_scalar if (!$requestors) and defined($cust_main); + my $subtype = $object->table; + my $pkey = $object->get($object->primary_key); + my %param = ( 'Queue' => ($cust_main->agent->ticketing_queueid || $default_queueid), - 'new-MemberOf'=> "freeside://freeside/cust_main/$custnum", + 'new-MemberOf'=> "freeside://freeside/$subtype/$pkey", 'Requestors' => $requestors, ); diff --git a/FS/FS/TicketSystem/RT_Internal.pm b/FS/FS/TicketSystem/RT_Internal.pm index d96e5f05f..ffa8c7c1c 100644 --- a/FS/FS/TicketSystem/RT_Internal.pm +++ b/FS/FS/TicketSystem/RT_Internal.pm @@ -107,10 +107,13 @@ properly. =cut -sub _customer_tickets_search { - my ( $self, $custnum, $limit, $priority ) = @_; +# create an RT::Tickets object for a specified custnum or svcnum - $custnum =~ /^\d+$/ or die "invalid custnum: $custnum"; +sub _tickets_search { + my ( $self, $type, $number, $limit, $priority ) = @_; + + $type =~ /^Customer|Service$/ or die "invalid type: $type"; + $number =~ /^\d+$/ or die "invalid custnum/svcnum: $number"; $limit =~ /^\d+$/ or die "invalid limit: $limit"; my $session = $self->session(); @@ -119,7 +122,8 @@ sub _customer_tickets_search { my $Tickets = RT::Tickets->new($CurrentUser); - my $rtql = "MemberOf = 'freeside://freeside/cust_main/$custnum'"; + # "Customer.number" searches tickets linked via cust_svc also + my $rtql = "$type.number = $number"; if ( defined( $priority ) ) { my $custom_priority = FS::Conf->new->config('ticket_system-custom_priority_field'); @@ -144,8 +148,25 @@ sub _customer_tickets_search { return $Tickets; } +sub href_customer_tickets { + my ($self, $custnum) = (shift, shift); + if ($custnum =~ /^(\d+)$/) { + return $self->href_search_tickets("Customer.number = $custnum"); + } + warn "bad custnum $custnum"; ''; +} + +sub href_service_tickets { + my ($self, $svcnum) = (shift, shift); + if ($svcnum =~ /^(\d+)$/ ) { + return $self->href_search_tickets("Service.number = $svcnum"); + } + warn "bad svcnum $svcnum"; ''; +} + sub customer_tickets { - my $Tickets = _customer_tickets_search(@_); + my $self = shift; + my $Tickets = $self->_tickets_search('Customer', @_); my $conf = FS::Conf->new; my $priority_order = @@ -168,8 +189,30 @@ sub customer_tickets { sub num_customer_tickets { my ( $self, $custnum, $priority ) = @_; - my $Tickets = $self->_customer_tickets_search($custnum, 0, $priority); - return $Tickets->CountAll; + $self->_tickets_search('Customer', $custnum, 0, $priority)->CountAll; +} + +sub service_tickets { + my $self = shift; + my $Tickets = $self->_tickets_search('Service', @_); + + my $conf = FS::Conf->new; + my $priority_order = + $conf->exists('ticket_system-priority_reverse') ? 'ASC' : 'DESC'; + + my @order_by = ( + { FIELD => 'Priority', ORDER => $priority_order }, + { FIELD => 'Id', ORDER => 'DESC' }, + ); + + $Tickets->OrderByCols(@order_by); + + my @tickets; + while ( my $t = $Tickets->Next ) { + push @tickets, _ticket_info($t); + } + + return \@tickets; } sub _ticket_info { @@ -200,6 +243,12 @@ sub _ticket_info { if ( $ss_priority ) { $ticket_info{'_selfservice_priority'} = $ticket_info{"CF.{$ss_priority}"}; } + my $svcnums = [ + map { $_->Target =~ /cust_svc\/(\d+)/; $1 } + @{ $t->Services->ItemsArrayRef } + ]; + $ticket_info{'svcnums'} = $svcnums; + return \%ticket_info; } diff --git a/FS/FS/cust_svc.pm b/FS/FS/cust_svc.pm index fc6e60594..a52791385 100644 --- a/FS/FS/cust_svc.pm +++ b/FS/FS/cust_svc.pm @@ -756,8 +756,94 @@ sub get_session_history { } +=item tickets + +Returns an array of hashes representing the tickets linked to this service. + +=cut + +sub tickets { + my $self = shift; + + my $conf = FS::Conf->new; + my $num = $conf->config('cust_main-max_tickets') || 10; + my @tickets = (); + + if ( $conf->config('ticket_system') ) { + unless ( $conf->config('ticket_system-custom_priority_field') ) { + + @tickets = @{ FS::TicketSystem->service_tickets($self->svcnum, $num) }; + + } else { + + foreach my $priority ( + $conf->config('ticket_system-custom_priority_field-values'), '' + ) { + last if scalar(@tickets) >= $num; + push @tickets, + @{ FS::TicketSystem->service_tickets( $self->svcnum, + $num - scalar(@tickets), + $priority, + ) + }; + } + } + } + (@tickets); +} + + =back +=head1 SUBROUTINES + +=over 4 + +=item smart_search OPTION => VALUE ... + +Accepts the option I, the string to search for. The string will +be searched for as a username, email address, IP address, MAC address, +phone number, and hardware serial number. Unlike the I on +customers, this always requires an exact match. + +=cut + +# though perhaps it should be fuzzy in some cases? +sub smart_search { + my %opt = @_; + # some false laziness w/ search/cust_svc.html + my $string = $opt{'search'}; + $string =~ s/(^\s+|\s+$)//; #trim leading & trailing whitespace + + my @extra_sql = ' ( '. join(' OR ', + map { my $table = $_; + my $search_sql = "FS::$table"->search_sql($string); + " ( svcdb = '$table' + AND 0 < ( SELECT COUNT(*) FROM $table + WHERE $table.svcnum = cust_svc.svcnum + AND $search_sql + ) + ) "; + } + FS::part_svc->svc_tables + ). ' ) '; + push @extra_sql, $FS::CurrentUser::CurrentUser->agentnums_sql( + 'null_right' => 'View/link unlinked services' + ); + my $extra_sql = ' WHERE '.join(' AND ', @extra_sql); + #for agentnum + my $addl_from = ' LEFT JOIN cust_pkg USING ( pkgnum )'. + ' LEFT JOIN cust_main USING ( custnum )'. + ' LEFT JOIN part_svc USING ( svcpart )'; + + qsearch({ + 'table' => 'cust_svc', + 'addl_from' => $addl_from, + 'hashref' => {}, + 'extra_sql' => $extra_sql, + }); +} + =head1 BUGS Behaviour of changing the svcpart of cust_svc records is undefined and should diff --git a/FS/FS/svc_phone.pm b/FS/FS/svc_phone.pm index 118748ea2..b395ea605 100644 --- a/FS/FS/svc_phone.pm +++ b/FS/FS/svc_phone.pm @@ -218,13 +218,14 @@ Class method which returns an SQL fragment to search for the given string. sub search_sql { my( $class, $string ) = @_; + my $conf = new FS::Conf; + if ( $conf->exists('svc_phone-allow_alpha_phonenum') ) { $string =~ s/\W//g; } else { $string =~ s/\D//g; } - my $conf = new FS::Conf; my $ccode = ( $conf->exists('default_phone_countrycode') && $conf->config('default_phone_countrycode') ) diff --git a/httemplate/elements/form-create_ticket.html b/httemplate/elements/form-create_ticket.html new file mode 100644 index 000000000..362e82397 --- /dev/null +++ b/httemplate/elements/form-create_ticket.html @@ -0,0 +1,38 @@ +
+ +Tickets +<% mt('Create new ticket') |h %> + <% mt('in queue') |h %> +%# fetch list of queues in which the user can create tickets +% my %queues = FS::TicketSystem->queues('', 'CreateTicket'); +% if( $conf->exists('ticket_system-force_default_queueid') ) { +<% $queues{$new_param{'Queue'}} %> + +% } +% else { + + +% } + +<%init> +my %opt = @_; +my $conf = new FS::Conf; +my $object = $opt{'object'}; # must be a cust_main, cust_svc, or svc_... +my ($new_base, %new_param) = FS::TicketSystem->href_params_new_ticket($object); +my $new_link = FS::TicketSystem->href_new_ticket($object); + diff --git a/httemplate/elements/table-tickets.html b/httemplate/elements/table-tickets.html new file mode 100644 index 000000000..6d1a45a0d --- /dev/null +++ b/httemplate/elements/table-tickets.html @@ -0,0 +1,159 @@ +<& /elements/form-create_ticket.html, object => $object &> + | +View +<% mt($openlabel) |h %> | +<% mt('resolved') |h %> +
+ +<& /elements/table-grid.html &> +% my $bgcolor1 = '#eeeeee'; +% my $bgcolor2 = '#ffffff'; +% my $bgcolor = ''; + +
+ + + + + + + + +% if ( $ss_priority ) { + +% } +% if ( $object->isa('FS::cust_main') ) { + +% } + + +% foreach my $ticket ( @tickets ) { +% my $href = FS::TicketSystem->href_ticket($ticket->{id}); +% if ( $bgcolor eq $bgcolor1 ) { +% $bgcolor = $bgcolor2; +% } else { +% $bgcolor = $bgcolor1; +% } + + + + + + + + + + + + + + + + + + + +% if ( $ss_priority ) { + +% } +% if ( $object->isa('FS::cust_main') ) { + +% } + + + +% } + +
- + " + + ><% $param->{"status$row"} %> + " + rownum = "<% $row %>" + > + " rownum = "<% $row %>" - STYLE = "text-align:center; font-weight: bold" > - @@ -456,6 +429,21 @@ Example: + <% $money_char %> + <% $param->{"balance$row"} %> +   + " + rownum = "<% $row %>" + > + - - -   -
tax eq "Y" ? 'CHECKED' : '' %>> Tax Exempt<% @exempt_groups ? ' (all taxes)' : '' %>
tax eq "Y" ? 'CHECKED' : '' %>> Tax Exempt<% @exempt_groups ? ' (all taxes)' : '' %>
<% mt('Tax exempt') |h %><% @exempt_groups ? ' ('.emt('all taxes').')' : '' %><% $cust_main->tax ? $yes : $no %>
<% mt('Tax exempt') |h %><% @exempt_groups ? ' ('.emt('all taxes').')' : '' %><% $cust_main->tax ? $yes : $no %>
<% mt('Tax exempt') |h %> (<% $exempt_group %> taxes)<% $cust_main->tax_exemption($exempt_group) ? $yes : $no %>
<% mt('Tax exempt') |h %> (<% $exempt_group %> taxes)<% $cust_main->tax_exemption($exempt_group) ? $yes : $no %>
<% mt('#') |h %><% mt('Subject') |h %><% mt('Status') |h %><% mt('Queue') |h %><% mt('Owner') |h %><% mt('Due') |h %><% mt('Estimated Time') |h %><% mt('Priority') |h %><% mt('Customer Priority') |h %><% mt('Service') |h %>
+ ><% $ticket->{id} %> + + ><% $ticket->{subject} %> + + <% $ticket->{status} %> + + <% $ticket->{queue} %> + + <% $ticket->{owner} %> + + <% $date_formatter->($ticket->{due}) %> + + <% $ticket->{timeestimated} %> + + <% $ticket->{content} + ? $ticket->{content}.' ('.$ticket->{priority}.')' + : $ticket->{priority} + %> + + <% $ticket->{"CF.{$ss_priority}"} %> + +% foreach (@{ $ticket->{svcnums} }) { +% my $cust_svc = FS::cust_svc->by_key($_) or next; + <% FS::UI::Web::svc_label_link($m, $cust_svc->part_svc, $cust_svc) %> +
+% } +
+ +<%init> +use Date::Parse qw(str2time); +use Date::Format qw(time2str); + +my %opt = @_; +my $conf = new FS::Conf; + +my $object = $opt{'object'}; +$object = $object->cust_svc if $object->isa('FS::svc_Common'); +my( @tickets ) = $object->tickets; + +my ($openlabel, $open_link, $res_link, $thing); +$openlabel = join('/', FS::TicketSystem->statuses ); + +# not the nicest way to do this--FS::has_tickets_Common? +if ( $object->isa('FS::cust_main') ) { + $thing = 'customer'; + $open_link = FS::TicketSystem->href_customer_tickets($object->custnum); + + $res_link = FS::TicketSystem->href_customer_tickets( + $object->custnum, + { 'statuses' => [ 'resolved' ] } + ); +} +elsif ( $object->isa('FS::cust_svc') ) { + $thing = 'service'; + $open_link = FS::TicketSystem->href_service_tickets($object->svcnum); + + $res_link = FS::TicketSystem->href_service_tickets( + $object->svcnum, + { 'statuses' => [ 'resolved' ] } + ); +} + +my $ss_priority = FS::TicketSystem->selfservice_priority; +if ( $ss_priority ) { + my $dir = $conf->exists('ticket_system-priority_reverse') ? -1 : 1; + use sort 'stable'; + # sort in the following way: + @tickets = sort { + # within a severity level... + ( $a->{'content'} eq $b->{'content'} ) ? ( + # no-priority tickets sort last + ( + ($a->{'_selfservice_priority'} eq '') <=> + ($b->{'_selfservice_priority'} eq '') + ) || + # otherwise obey ticket_system-priority_reverse + ( $dir * + ($b->{'_selfservice_priority'} <=> $a->{'_selfservice_priority'}) + ) + ) : 0; # but don't rearrange between severity levels + } @tickets; +} + +my $format = $conf->config('date_format') || '%Y-%m-%d'; + +my $date_formatter = sub { + my $time = str2time($_[0], 'GMT'); + # exclude times within 24 hours of zero + ($time > 86400) ? time2str($format, $time) : ''; +}; + + diff --git a/httemplate/view/cust_main/tickets.html b/httemplate/view/cust_main/tickets.html index 194e90742..f076fcc92 100644 --- a/httemplate/view/cust_main/tickets.html +++ b/httemplate/view/cust_main/tickets.html @@ -1,164 +1,2 @@ -
- -Tickets -<% mt('Create new ticket') |h %> - <% mt('in queue') |h %> -%# fetch list of queues in which the user can create tickets -% my %queues = FS::TicketSystem->queues('', 'CreateTicket'); -% if( $conf->exists('ticket_system-force_default_queueid') ) { -<% $queues{$new_param{'Queue'}} %> - -% } -% else { - - -% } -
- | -View -<% mt($openlabel) |h %> | -<% mt('resolved') |h %> -
- -<& /elements/table-grid.html &> -% my $bgcolor1 = '#eeeeee'; -% my $bgcolor2 = '#ffffff'; -% my $bgcolor = ''; - - - <% mt('#') |h %> - <% mt('Subject') |h %> - <% mt('Status') |h %> - <% mt('Queue') |h %> - <% mt('Owner') |h %> - <% mt('Due') |h %> - <% mt('Estimated Time') |h %> - <% mt('Priority') |h %> -% if ( $ss_priority ) { - <% mt('Customer Priority') |h %> -% } - - -% foreach my $ticket ( @tickets ) { -% my $href = FS::TicketSystem->href_ticket($ticket->{id}); -% if ( $bgcolor eq $bgcolor1 ) { -% $bgcolor = $bgcolor2; -% } else { -% $bgcolor = $bgcolor1; -% } - - - - - ><% $ticket->{id} %> - - - - ><% $ticket->{subject} %> - - - - <% $ticket->{status} %> - - - - <% $ticket->{queue} %> - - - - <% $ticket->{owner} %> - - - - <% $date_formatter->($ticket->{due}) %> - - - - <% $ticket->{timeestimated} %> - - - - <% $ticket->{content} - ? $ticket->{content}.' ('.$ticket->{priority}.')' - : $ticket->{priority} - %> - - -% if ( $ss_priority ) { - - <% $ticket->{"CF.{$ss_priority}"} %> - -% } - - - -% } - - - -<%init> -use Date::Format 'time2str'; -use Date::Parse 'str2time'; - -my( $conf ) = new FS::Conf; -my( $cust_main ) = @_; -my( @tickets ) = $cust_main->tickets; - -my $open_link = FS::TicketSystem->href_customer_tickets($cust_main->custnum); -my $openlabel = join('/', FS::TicketSystem->statuses ); - -my $res_link = FS::TicketSystem->href_customer_tickets( - $cust_main->custnum, - { 'statuses' => [ 'resolved' ] } - ); - -my( $new_base, %new_param ) = - FS::TicketSystem->href_params_new_ticket( $cust_main ); - -my $new_link = FS::TicketSystem->href_new_ticket( $cust_main ); - -my $ss_priority = FS::TicketSystem->selfservice_priority; -if ( $ss_priority ) { - my $dir = $conf->exists('ticket_system-priority_reverse') ? -1 : 1; - use sort 'stable'; - # sort in the following way: - @tickets = sort { - # within a severity level... - ( $a->{'content'} eq $b->{'content'} ) ? ( - # no-priority tickets sort last - ( - ($a->{'_selfservice_priority'} eq '') <=> - ($b->{'_selfservice_priority'} eq '') - ) || - # otherwise obey ticket_system-priority_reverse - ( $dir * - ($b->{'_selfservice_priority'} <=> $a->{'_selfservice_priority'}) - ) - ) : 0; # but don't rearrange between severity levels - } @tickets; -} - -my $format = $conf->config('date_format') || '%Y-%m-%d'; - -my $date_formatter = sub { - my $time = str2time($_[0], 'GMT'); - # exclude times within 24 hours of zero - ($time > 86400) ? time2str($format, $time) : ''; -}; - - +% my $cust_main = shift; +<& /elements/table-tickets.html, object => $cust_main &> diff --git a/httemplate/view/elements/svc_Common.html b/httemplate/view/elements/svc_Common.html index 3130c73a0..04d2b2962 100644 --- a/httemplate/view/elements/svc_Common.html +++ b/httemplate/view/elements/svc_Common.html @@ -114,6 +114,10 @@ function areyousure(href) { % } +% if ( $conf->config('ticket_system') ) { +<& /elements/table-tickets.html, object => $cust_svc &> +% } + <% joblisting({'svcnum'=>$svcnum}, 1) %> <% include('/elements/footer.html') %> diff --git a/httemplate/view/svc_acct.cgi b/httemplate/view/svc_acct.cgi index 441e4945d..de97a0796 100755 --- a/httemplate/view/svc_acct.cgi +++ b/httemplate/view/svc_acct.cgi @@ -75,6 +75,10 @@ <& elements/svc_export_settings.html, $svc_acct &> +% if ( $conf->config('ticket_system') ) { +<& /elements/table-tickets.html, object => $cust_svc &> +% } + <% joblisting({'svcnum'=>$svcnum}, 1) %> <& /elements/footer.html &> diff --git a/httemplate/view/svc_domain.cgi b/httemplate/view/svc_domain.cgi index 3938a3406..fcccd74b4 100755 --- a/httemplate/view/svc_domain.cgi +++ b/httemplate/view/svc_domain.cgi @@ -36,6 +36,10 @@ <% include('elements/svc_export_settings.html', $svc_domain) %> +% if ( $conf->config('ticket_system') ) { +<& /elements/table-tickets.html, object => $cust_svc &> +% } + <% joblisting({'svcnum'=>$svcnum}, 1) %> <% include('/elements/footer.html') %> diff --git a/httemplate/view/svc_external.cgi b/httemplate/view/svc_external.cgi index 77679d81c..72e553598 100644 --- a/httemplate/view/svc_external.cgi +++ b/httemplate/view/svc_external.cgi @@ -23,6 +23,11 @@ + +% if ( $conf->config('ticket_system') ) { +<& /elements/table-tickets.html, object => $cust_svc &> +% } +
<% joblisting({'svcnum'=>$svcnum}, 1) %> <% include('/elements/footer.html') %> diff --git a/httemplate/view/svc_forward.cgi b/httemplate/view/svc_forward.cgi index 15b5ae56f..2cb78ebd5 100755 --- a/httemplate/view/svc_forward.cgi +++ b/httemplate/view/svc_forward.cgi @@ -53,6 +53,10 @@ <% include('elements/svc_export_settings.html', $svc_forward) %> +% if ( $conf->config('ticket_system') ) { +<& /elements/table-tickets.html, object => $cust_svc &> +% } + <% joblisting({'svcnum'=>$svcnum}, 1) %> <% include('/elements/footer.html') %> diff --git a/httemplate/view/svc_www.cgi b/httemplate/view/svc_www.cgi index 935d139e9..fbb02a00f 100644 --- a/httemplate/view/svc_www.cgi +++ b/httemplate/view/svc_www.cgi @@ -49,6 +49,10 @@
+% if ( $conf->config('ticket_system') ) { +<& /elements/table-tickets.html, object => $cust_svc &> +% } + <% joblisting({'svcnum'=>$svcnum}, 1) %> <% include('/elements/footer.html') %> diff --git a/rt/lib/RT/Interface/Web_Vendor.pm b/rt/lib/RT/Interface/Web_Vendor.pm index ee8c34b55..ae7f0899a 100644 --- a/rt/lib/RT/Interface/Web_Vendor.pm +++ b/rt/lib/RT/Interface/Web_Vendor.pm @@ -75,13 +75,33 @@ sub ProcessTicketCustomers { } ### + ### + #find new services + ### + + my @svcnums = map { /^Ticket-AddService-(\d+)$/; $1 } + grep { /^Ticket-AddService-(\d+)$/ && $ARGSRef->{$_} } + keys %$ARGSRef; + + my @custnums; + foreach my $svcnum (@svcnums) { + my @link = ( 'Type' => 'MemberOf', + 'Target' => "freeside://freeside/cust_svc/$svcnum", + ); + + my( $val, $msg ) = $Ticket->AddLink(@link); + push @results, $msg; + next if !$val; + + } + ### #find new customers ### - my @custnums = map { /^Ticket-AddCustomer-(\d+)$/; $1 } - grep { /^Ticket-AddCustomer-(\d+)$/ && $ARGSRef->{$_} } - keys %$ARGSRef; + push @custnums, map { /^Ticket-AddCustomer-(\d+)$/; $1 } + grep { /^Ticket-AddCustomer-(\d+)$/ && $ARGSRef->{$_} } + keys %$ARGSRef; #my @delete_custnums = # map { /^Ticket-AddCustomer-(\d+)$/; $1 } diff --git a/rt/lib/RT/Record.pm b/rt/lib/RT/Record.pm index 121c08686..41e60bd84 100755 --- a/rt/lib/RT/Record.pm +++ b/rt/lib/RT/Record.pm @@ -1177,7 +1177,9 @@ sub DependsOn { =head2 Customers - This returns an RT::Links object which references all the customers that this object is a member of. + This returns an RT::Links object which references all the customers that + this object is a member of. This includes both explicitly linked customers + and links implied by services. =cut @@ -1189,11 +1191,16 @@ sub Customers { $self->{'Customers'} = $self->MemberOf->Clone; - $self->{'Customers'}->Limit( - FIELD => 'Target', - OPERATOR => 'STARTSWITH', - VALUE => 'freeside://freeside/cust_main/', - ); + for my $fstable (qw(cust_main cust_svc)) { + + $self->{'Customers'}->Limit( + FIELD => 'Target', + OPERATOR => 'STARTSWITH', + VALUE => "freeside://freeside/$fstable", + ENTRYAGGREGATOR => 'OR', + SUBCLAUSE => 'customers', + ); + } } warn "->Customers method called on $self; returning ". @@ -1205,6 +1212,34 @@ sub Customers { # }}} +# {{{ Services + +=head2 Services + + This returns an RT::Links object which references all the services this + object is a member of. + +=cut + +sub Services { + my( $self, %opt ) = @_; + + unless ( $self->{'Services'} ) { + + $self->{'Services'} = $self->MemberOf->Clone; + + $self->{'Services'}->Limit( + FIELD => 'Target', + OPERATOR => 'STARTSWITH', + VALUE => "freeside://freeside/cust_svc", + ); + } + + return $self->{'Services'}; +} + +# }}} + # {{{ sub _Links =head2 Links DIRECTION [TYPE] diff --git a/rt/lib/RT/Tickets_Overlay.pm b/rt/lib/RT/Tickets_Overlay.pm index a5d37a378..0d482cd04 100644 --- a/rt/lib/RT/Tickets_Overlay.pm +++ b/rt/lib/RT/Tickets_Overlay.pm @@ -146,11 +146,8 @@ our %FIELD_METADATA = ( HasAttribute => [ 'HASATTRIBUTE', 1 ], HasNoAttribute => [ 'HASATTRIBUTE', 0 ], #freeside - Customer => [ 'FREESIDEFIELD', ], -# Agentnum => [ 'FREESIDEFIELD', ], -# Classnum => [ 'FREESIDEFIELD', ], -# Refnum => [ 'FREESIDEFIELD', ], -# Tagnum => [ 'FREESIDEFIELD', 'cust_tag' ], + Customer => [ 'FREESIDEFIELD' => 'Customer' ], + Service => [ 'FREESIDEFIELD' => 'Service' ], WillResolve => [ 'DATE' => 'WillResolve', ], #loc_left_pair ); @@ -1823,6 +1820,15 @@ sub OrderByCols { } push @res, { %$row, ALIAS => $custalias, FIELD => $cust_field }; + } elsif ( $field eq 'Service' ) { + + my $svcalias = $self->JoinToService; + my $svc_field = lc($subkey); + if ( !$svc_field or $svc_field eq 'number' ) { + $svc_field = 'svcnum'; + } + push @res, { %$row, ALIAS => $svcalias, FIELD => $svc_field }; + } #Freeside else { @@ -1842,7 +1848,7 @@ sub JoinToCustLinks { # and an sql expression to retrieve the custnum. my $self = shift; # only join once for each RT::Tickets object - my $linkalias = $self->{cust_linkalias}; + my $linkalias = $self->{cust_main_linkalias}; if (!$linkalias) { $linkalias = $self->Join( TYPE => 'LEFT', @@ -1864,7 +1870,7 @@ sub JoinToCustLinks { OPERATOR => 'STARTSWITH', VALUE => 'freeside://freeside/cust_main/', ); - $self->{cust_linkalias} = $linkalias; + $self->{cust_main_linkalias} = $linkalias; } my $custnum_sql = "CAST(SUBSTR($linkalias.Target,31) AS "; if ( RT->Config->Get('DatabaseType') eq 'mysql' ) { @@ -1890,9 +1896,79 @@ sub JoinToCustomer { return $custalias; } +sub JoinToSvcLinks { + my $self = shift; + my $linkalias = $self->{cust_svc_linkalias}; + if (!$linkalias) { + $linkalias = $self->Join( + TYPE => 'LEFT', + ALIAS1 => 'main', + FIELD1 => 'id', + TABLE2 => 'Links', + FIELD2 => 'LocalBase', + ); + + $self->SUPER::Limit( + LEFTJOIN => $linkalias, + FIELD => 'Type', + OPERATOR => '=', + VALUE => 'MemberOf', + ); + $self->SUPER::Limit( + LEFTJOIN => $linkalias, + FIELD => 'Target', + OPERATOR => 'STARTSWITH', + VALUE => 'freeside://freeside/cust_svc/', + ); + $self->{cust_svc_linkalias} = $linkalias; + } + my $svcnum_sql = "CAST(SUBSTR($linkalias.Target,30) AS "; + if ( RT->Config->Get('DatabaseType') eq 'mysql' ) { + $svcnum_sql .= 'SIGNED INTEGER)'; + } + else { + $svcnum_sql .= 'INTEGER)'; + } + return ($linkalias, $svcnum_sql); +} + +sub JoinToService { + my $self = shift; + my ($linkalias, $svcnum_sql) = $self->JoinToSvcLinks; + $self->Join( + TYPE => 'LEFT', + EXPRESSION => $svcnum_sql, + TABLE2 => 'cust_svc', + FIELD2 => 'svcnum', + ); +} + +# This creates an alternate left join path to cust_main via cust_svc. +# _FreesideFieldLimit needs to add this as a separate, independent join +# and include all tickets that have a matching cust_main record via +# either path. +sub JoinToCustomerViaService { + my $self = shift; + my $svcalias = $self->JoinToService; + my $cust_pkg = $self->Join( + TYPE => 'LEFT', + ALIAS1 => $svcalias, + FIELD1 => 'pkgnum', + TABLE2 => 'cust_pkg', + FIELD2 => 'pkgnum', + ); + my $cust_main = $self->Join( + TYPE => 'LEFT', + ALIAS1 => $cust_pkg, + FIELD1 => 'custnum', + TABLE2 => 'cust_main', + FIELD2 => 'custnum', + ); + $cust_main; +} + sub _FreesideFieldLimit { my ( $self, $field, $op, $value, %rest ) = @_; - my $alias = $self->JoinToCustomer; my $is_negative = 0; if ( $op eq '!=' || $op =~ /\bNOT\b/i ) { # if the op is negative, do the join as though @@ -1903,40 +1979,70 @@ sub _FreesideFieldLimit { $op =~ s/\bNOT\b//; } - my $cust_field = $rest{SUBKEY} || 'custnum'; + my (@alias, $table2, $subfield, $pkey); + if ( $field eq 'Customer' ) { + push @alias, $self->JoinToCustomer; + push @alias, $self->JoinToCustomerViaService; + $pkey = 'custnum'; + } + elsif ( $field eq 'Service' ) { + push @alias, $self->JoinToService; + $pkey = 'svcnum'; + } + else { + die "malformed Freeside query: $field"; + } + + $subfield = $rest{SUBKEY} || $pkey; my $table2; # compound subkey: separate into table name and field in that table # (must be linked by custnum) - ($table2, $cust_field) = ($1, $2) if $cust_field =~ /^(\w+)?\.(\w+)$/; - - $cust_field = lc($cust_field); - $cust_field = 'custnum' if !$cust_field or $cust_field eq 'number'; - - if ( $table2 ) { - $alias = $self->Join( - TYPE => 'LEFT', - ALIAS1 => $alias, - FIELD1 => 'custnum', - TABLE2 => $table2, - FIELD2 => 'custnum', - ); + $subfield = lc($subfield); + ($table2, $subfield) = ($1, $2) if $subfield =~ /^(\w+)?\.(\w+)$/; + $subfield = $pkey if $subfield eq 'number'; + + # if it's compound, create a join from cust_main or cust_svc to that + # table, using custnum or svcnum, and Limit on that table instead. + foreach my $a (@alias) { + if ( $table2 ) { + $a = $self->Join( + TYPE => 'LEFT', + ALIAS1 => $a, + FIELD1 => $pkey, + TABLE2 => $table2, + FIELD2 => $pkey, + ); + } + + # do the actual Limit + $self->SUPER::Limit( + LEFTJOIN => $a, + FIELD => $subfield, + OPERATOR => $op, + VALUE => $value, + ENTRYAGGREGATOR => 'AND', + # no SUBCLAUSE needed, limits on different aliases across left joins + # are inherently independent + ); + + # then, since it's a left join, exclude tickets for which there is now + # no matching record in the table we just limited on. (Or where there + # is a matching record, if $is_negative.) + # For a cust_main query (where there are two different aliases), this + # will produce a subclause: "cust_main_1.custnum IS NOT NULL OR + # cust_main_2.custnum IS NOT NULL" (or "IS NULL AND..." for a negative + # query). + $self->_SQLLimit( + %rest, + ALIAS => $a, + FIELD => $pkey, + OPERATOR => $is_negative ? 'IS' : 'IS NOT', + VALUE => 'NULL', + QUOTEVALUE => 0, + ENTRYAGGREGATOR => $is_negative ? 'AND' : 'OR', + SUBCLAUSE => 'fs_limit', + ); } - - $self->SUPER::Limit( - LEFTJOIN => $alias, - FIELD => $cust_field, - OPERATOR => $op, - VALUE => $value, - ENTRYAGGREGATOR => 'AND', - ); - $self->_SQLLimit( - %rest, - ALIAS => $alias, - FIELD => 'custnum', - OPERATOR => $is_negative ? 'IS' : 'IS NOT', - VALUE => 'NULL', - QUOTEVALUE => 0, - ); } #Freeside diff --git a/rt/lib/RT/URI/freeside/Internal.pm b/rt/lib/RT/URI/freeside/Internal.pm index 5656a51d8..b5e56ee1f 100644 --- a/rt/lib/RT/URI/freeside/Internal.pm +++ b/rt/lib/RT/URI/freeside/Internal.pm @@ -38,8 +38,14 @@ use FS::Conf; use FS::Record qw(qsearchs qsearch dbdef); use FS::cust_main; use FS::cust_svc; +use FS::part_svc; use FS::payby; +#can I do this? +FS::UID->install_callback( + sub { @RT::URI::freeside::svc_tables = FS::part_svc->svc_tables() } +); + =head1 NAME RT::URI::freeside::Internal @@ -105,7 +111,23 @@ sub FreesideGetConfig { sub smart_search { #Subroutine - return map { { $_->hash } } &FS::cust_main::Search::smart_search(@_); + return map { { $_->hash } } &FS::cust_main::Search::smart_search(@_); + +} + +sub service_search { + + return map { + my $cust_pkg = $_->cust_pkg; + my $custnum = $cust_pkg->custnum if $cust_pkg; + my $label = join(': ',($_->label)[0, 1]); + my %hash = ( + $_->hash, + 'label' => $label, + 'custnum' => $custnum, # so that it's smart_searchable... + ); + \%hash + } &FS::cust_svc::smart_search(@_); } @@ -130,10 +152,22 @@ sub _FreesideURILabelLong { if ( $table eq 'cust_main' ) { my $rec = $self->_FreesideGetRecord(); - return small_custview( $rec->{'_object'}, + return '' . + small_custview( $rec->{'_object'}, scalar(FS::Conf->new->config('countrydefault')), - 1 #nobalance - ); + 1, #nobalance + ) . ''; + + } elsif ( $table eq 'cust_svc' ) { + + my $string = ''; + my $cust = $self->CustomerResolver; + if ( $cust ) { + $string = $cust->AsStringLong; + } + $string .= '' . + $self->AsString . ''; + return $string; } else { @@ -143,18 +177,36 @@ sub _FreesideURILabelLong { } -# no need to have a separate wrapper method for every one of these things +sub CustomerResolver { + my $self = shift; + if ( $self->{fstable} eq 'cust_main' ) { + return $self; + } + elsif ( $self->{fstable} eq 'cust_svc' ) { + my $rec = $self->_FreesideGetRecord(); + return if !$rec; + my $cust_pkg = $rec->{'_object'}->cust_pkg; + if ( $cust_pkg ) { + my $URI = RT::URI->new($self->CurrentUser); + $URI->FromURI('freeside://freeside/cust_main/'.$cust_pkg->custnum); + return $URI->Resolver; + } + } + return; +} + sub CustomerInfo { my $self = shift; + $self = $self->CustomerResolver or return; my $rec = $self->_FreesideGetRecord() or return; - my $cust_main = $rec->{'_object'}; + my $cust_main = delete $rec->{_object}; my $agent = $cust_main->agent; my $class = $cust_main->cust_class; my $referral = qsearchs('part_referral', { refnum => $cust_main->refnum }); my @part_tags = $cust_main->part_tag; return $self->{CustomerInfo} ||= { - $cust_main->hash, + %$rec, AgentName => ($agent ? ($agent->agentnum.': '.$agent->agent) : ''), CustomerClass => ($class ? $class->classname : ''), @@ -170,4 +222,19 @@ sub CustomerInfo { } } +sub ServiceInfo { + my $self = shift; + $self->{fstable} eq 'cust_svc' or return; + my $rec = $self->_FreesideGetRecord() or return; + my $cust_svc = $rec->{'_object'}; + my $svc_x = $cust_svc->svc_x; + my $part_svc = $cust_svc->part_svc; + return $self->{ServiceInfo} ||= { + $cust_svc->hash, + $svc_x->hash, + ServiceType => $part_svc->svc, + Label => $self->AsString, + } +} + 1; diff --git a/rt/share/html/Elements/CustomerFields b/rt/share/html/Elements/CustomerFields index 553a34999..d5419d213 100644 --- a/rt/share/html/Elements/CustomerFields +++ b/rt/share/html/Elements/CustomerFields @@ -16,7 +16,6 @@ About the keys: name to sort by. <%once> -return unless $RT::URI::freeside::IntegrationType eq 'Internal'; my @customer_fields = ( # ordered { @@ -158,8 +157,12 @@ sub select_table { sub ticket_cust_resolvers { my $Ticket = shift; - my @Customers = @{ $Ticket->Customers->ItemsArrayRef }; - return map $_->TargetURI->Resolver, @Customers; + my @Customers = map { $_->TargetURI->Resolver->CustomerResolver } + @{ $Ticket->Customers->ItemsArrayRef }; + # this can contain cust_svc links, careful + # uniq + my %seen = map { $_->URI => $_ } @Customers; + values %seen; } sub cust_info_attribute { # the simple case of $resolver->CustomerInfo->{foo} @@ -177,7 +180,6 @@ sub cust_info_attribute { # the simple case of $resolver->CustomerInfo->{foo} <%init> -return unless $RT::URI::freeside::IntegrationType eq 'Internal'; my $arg = shift; if ( $arg eq 'Names' ) { @@ -198,9 +200,11 @@ elsif ( $arg eq 'ColumnMap' ) { grep { exists $_->{Display} } @customer_fields; } -elsif ( $arg eq 'PickBasics' ) { +elsif ( $arg eq 'Criteria' ) { return map { my $f = $_; + # argument to Search/Elements/ConditionRow + $f->{Condition} || { Name => ($f->{QueryName} || $f->{Name}), Field => ($f->{QueryLabel} || $f->{Label}), @@ -208,7 +212,7 @@ elsif ( $arg eq 'PickBasics' ) { Value => $f->{Value}, } } #map - grep { exists $_->{Value} } + grep { exists $_->{Condition} || exists $_->{Value} } @customer_fields; } else { die "unknown CustomerFields mode '$arg'\n"; } diff --git a/rt/share/html/Elements/RT__Ticket/ColumnMap b/rt/share/html/Elements/RT__Ticket/ColumnMap index 9e6466cdd..35c0aad86 100644 --- a/rt/share/html/Elements/RT__Ticket/ColumnMap +++ b/rt/share/html/Elements/RT__Ticket/ColumnMap @@ -321,6 +321,7 @@ $COLUMN_MAP = { #freeside $m->comp('/Elements/CustomerFields', 'ColumnMap'), + $m->comp('/Elements/ServiceFields', 'ColumnMap'), }; # if no GPG support, then KeyOwnerName and KeyRequestors fall back to the regular diff --git a/rt/share/html/Elements/ServiceFields b/rt/share/html/Elements/ServiceFields new file mode 100644 index 000000000..9c9a248c8 --- /dev/null +++ b/rt/share/html/Elements/ServiceFields @@ -0,0 +1,161 @@ +<%doc> +Accessible Freeside svc_x fields go in here. RT::URI::freeside::Internal +pulls all fields from cust_svc and the svc_x tables into ServiceInfo(). +RT::Tickets_Overlay resolves "Service.foo" as "cust_svc.foo", and +"Service.svc_acct.bar" as "JOIN svc_acct USING (svcnum) ... svc_acct.bar". + +See /Elements/CustomerFields for notes on this data structure. + +<%once> + +my @service_fields = ( # ordered + { + # svcnum + Name => 'Service', + Label => 'Service', + Display => sub { + my $Ticket = shift; + my @return = (); + foreach my $s (ticket_svc_resolvers($Ticket)) { + push @return, \'', + $s->AsString, + \'', + \'
'; + } + pop @return; + @return; + }, + OrderBy => 'Service.Number', + }, + { + #Column name (format string) + Name => 'ServiceType', + # Column heading/query builder name + Label => 'Service Type', + # Column value (coderef, cust_svc/svc_x field, or ServiceInfo key) + Display => 'ServiceType', + # Query builder options + # RT-SQL field, defaults to Name + QueryName => 'Service.svcpart', + Op => equals_notequals, + Value => select_table('part_svc', 'svcpart', 'svc'), + # RT-SQL sort key (if any) + OrderBy => 'Service.svcpart', + }, + { + Name => 'ServiceKey', # loosely corresponds to smartsearch/label field + Label => '', + # not displayable + QueryLabel => { + Type => 'select', + Options => [ + 'Service.svc_acct.username' => loc('Username'), + 'Service.svc_phone.phonenum' => loc('Phone Number'), + 'Service.svc_broadband.ip_addr' => loc('IP Address'), + 'Service.svc_broadband.mac_addr' => loc('MAC Address'), + ], + }, + Op => matches_notmatches, + Value => { Type => 'text', Size => 20 }, + }, + { + Name => 'Router', + Label => 'Router', + QueryName => 'Service.svc_broadband.routernum', + # not displayable + Op => equals_notequals, + Value => select_table('router', 'routernum', 'routername'), + OrderBy => 'Service.svc_broadband.routernum', + }, + +); +#helper subs +#Op +sub equals_notequals { + { + Type => 'component', + Path => '/Elements/SelectBoolean', + Arguments => { TrueVal=> '=', FalseVal=> '!=' }, + } +} +sub matches_notmatches { + { + Type => 'component', + Path => '/Elements/SelectMatch', + }, +} + +#Value +sub select_table { + my ($table, $value_col, $name_col, $hashref) = @_; + $hashref ||= { disabled => '' }; # common case + return { + Type => 'select', + Options => [ + '' => '-', + map { $_->$value_col, $_->$name_col } + qsearch($table, $hashref) + ], + } +} + +sub ticket_svc_resolvers { + my $Ticket = shift; + my @Services = @{ $Ticket->Services->ItemsArrayRef }; + return map $_->TargetURI->Resolver, @Services; +} + +sub svc_info_attribute { + my $attribute = shift; + sub { + my $Ticket = shift; + my @return; + foreach my $s (ticket_svc_resolvers($Ticket)) { + push @return, $s->ServiceInfo->{$attribute}, '
'; + } + pop @return; #trailing
+ @return; + }; +} + + +<%init> +use Data::Dumper; +#warn Dumper(\@service_fields); + +my $arg = shift; +if ( $arg eq 'Names' ) { + return map { $_->{Name} } + grep { exists $_->{Display} } + @service_fields; +} +elsif ( $arg eq 'ColumnMap' ) { + return map { + my $f = $_; + $f->{Name} => { + title => $f->{Label}, + attribute => $f->{OrderBy} || '', + value => ref($f->{Display}) eq 'CODE' ? + $f->{Display} : + svc_info_attribute($f->{Display}) + } + } #map + grep { exists $_->{Display} } + @service_fields; +} +elsif ( $arg eq 'Criteria' ) { + return map { + my $f = $_; + # argument to Search/Elements/ConditionRow + { + Name => ($f->{QueryName} || $f->{Name}), + Field => ($f->{QueryLabel} || $f->{Label}), + Op => $f->{Op}, + Value => $f->{Value}, + } + } #map + grep { exists($_->{Value}) } + @service_fields; +} +else { die "unknown ServiceFields mode '$arg'\n"; } + diff --git a/rt/share/html/Search/Elements/BuildFormatString b/rt/share/html/Search/Elements/BuildFormatString index 96e6a2863..57c767911 100644 --- a/rt/share/html/Search/Elements/BuildFormatString +++ b/rt/share/html/Search/Elements/BuildFormatString @@ -76,6 +76,7 @@ my @fields = ( ), $m->comp('/Elements/CustomerFields', 'Names'), #freeside + $m->comp('/Elements/ServiceFields', 'Names'), #freeside qw( Status ExtendedStatus UpdateStatus diff --git a/rt/share/html/Search/Elements/PickBasics b/rt/share/html/Search/Elements/PickBasics index ff30f7c11..e9534237b 100644 --- a/rt/share/html/Search/Elements/PickBasics +++ b/rt/share/html/Search/Elements/PickBasics @@ -210,7 +210,6 @@ my @lines = ( ); #freeside -push @lines, $m->comp('/Elements/CustomerFields', 'PickBasics'); $m->callback( Conditions => \@lines ); diff --git a/rt/share/html/Search/Elements/PickCriteria b/rt/share/html/Search/Elements/PickCriteria index 44e3b7037..5eb112d17 100644 --- a/rt/share/html/Search/Elements/PickCriteria +++ b/rt/share/html/Search/Elements/PickCriteria @@ -52,6 +52,7 @@ <& PickBasics &> +<& PickCustomerFields &> <& PickCFs, cfqueues => \%cfqueues &>
diff --git a/rt/share/html/Search/Elements/PickCustomerFields b/rt/share/html/Search/Elements/PickCustomerFields new file mode 100644 index 000000000..96d8e47e7 --- /dev/null +++ b/rt/share/html/Search/Elements/PickCustomerFields @@ -0,0 +1,8 @@ +% if ( $RT::URI::freeside::IntegrationType eq 'Internal' ) { +% my @lines; +% push @lines, $m->comp('/Elements/CustomerFields', 'Criteria'); +% push @lines, $m->comp('/Elements/ServiceFields', 'Criteria'); +% foreach( @lines ) { +<& ConditionRow, Condition => $_ &> +% } +% } diff --git a/rt/share/html/Ticket/Elements/AddCustomers b/rt/share/html/Ticket/Elements/AddCustomers index 09acdfd3f..3c2c82add 100644 --- a/rt/share/html/Ticket/Elements/AddCustomers +++ b/rt/share/html/Ticket/Elements/AddCustomers @@ -13,15 +13,25 @@
<%$msg%>
-% if (@Customers) { +% if (@Customers or @Services) { -
(Check box to link) +
(Check box to link) % foreach my $customer (@Customers) { + +% } +% +% foreach my $service (@Services) { + + % } @@ -29,11 +39,21 @@ % } +<%once> +my $freeside_url = &RT::URI::freeside::FreesideURL(); + + +<%def .small_custview> +% my $cust = shift; +<% &RT::URI::freeside::small_custview($cust->{'custnum'}, &RT::URI::freeside::FreesideGetConfig, 1) |n %> + +<%def .small_svcview> +% my $svc = shift; +<% $svc->{'label'} %> + <%INIT> my ($msg); -my $freeside_url = &RT::URI::freeside::FreesideURL(); - my @Customers = (); if ( $CustomerString ) { @Customers = &RT::URI::freeside::smart_search( @@ -43,8 +63,11 @@ if ( $CustomerString ) { } my @Services = (); -if ($ServiceString) { - @Services = (); #service_search(); +if ( $ServiceString + and $RT::URI::freeside::IntegrationType eq 'Internal' ) { + @Services = RT::URI::freeside::service_search( + 'search' => $ServiceString, + ); } diff --git a/rt/share/html/Ticket/Elements/EditCustomers b/rt/share/html/Ticket/Elements/EditCustomers index 0ba6e447b..96207f4cc 100644 --- a/rt/share/html/Ticket/Elements/EditCustomers +++ b/rt/share/html/Ticket/Elements/EditCustomers @@ -12,7 +12,7 @@ %# General Public License for more details.
> - <% &RT::URI::freeside::small_custview($customer->{'custnum'}, &RT::URI::freeside::FreesideGetConfig('countrydefault'), 1) |n %> + <& .small_custview, $customer &> +
+ > + <& .small_custview, $service &> + <& .small_svcview, $service &>
- - + + +%# rowspan + + + + +%#rowspan... +
+

<&|/l&>Current Customers

@@ -25,33 +25,40 @@ %# <& ShowLink, URI => $link->TargetURI &>
- <% $link->TargetURI->Resolver->AsStringLong |n %> -
+ <% $link->TargetURI->Resolver->AsStringLong |n %> +

% }
- +
+

<&|/l&>New Customer Links

-<&|/l&>Find customer
- - -
cust #, name, company or phone -
-%#
-%#<&|/l&>Find service
-%# -%# -%#
username, username@domain, domain, or IP address -%#
- +
+ <&|/l&>Find customer
+ + +
cust #, name, company or phone +
+ <&|/l&>Find service
+ + +
user, email, ip, mac, phone +
<& AddCustomers, Ticket => $Ticket, CustomerString => $CustomerString, - ServiceString => $ServiceString, &> - + ServiceString => $ServiceString &>
diff --git a/rt/share/html/Ticket/Elements/ShowCustomers b/rt/share/html/Ticket/Elements/ShowCustomers index 3acf92dd4..add562440 100644 --- a/rt/share/html/Ticket/Elements/ShowCustomers +++ b/rt/share/html/Ticket/Elements/ShowCustomers @@ -10,20 +10,19 @@ %# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU %# General Public License for more details. -% my $cust = 0; -% foreach my $custResolver ( map { $_->TargetURI->Resolver } -% @{ $Ticket->Customers->ItemsArrayRef } -% ) -% { -% $cust++; -% my $cust_main = ''; +% my @cust = map { $_->TargetURI->Resolver } +% @{ $Ticket->Customers->ItemsArrayRef }; +% +% foreach my $custResolver ( @cust ) { % } -% unless ( $cust ) { + +% unless ( @cust ) { - + + + + + + + + + + + +<%INIT> + +<%ARGS> +$EditClass => 1 +$ClassObj => undef +$ArticleObj => undef + diff --git a/rt/share/html/Articles/Article/Elements/EditCustomFields b/rt/share/html/Articles/Article/Elements/EditCustomFields new file mode 100644 index 000000000..db719eb2e --- /dev/null +++ b/rt/share/html/Articles/Article/Elements/EditCustomFields @@ -0,0 +1,83 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} +% while (my $CustomField = $CustomFields->Next()) { + + + + +% } +<%INIT> +my $CustomFields; +my $NamePrefix; + +if ($ArticleObj->id && $ArticleObj->ClassObj->id) { + $CustomFields = $ArticleObj->CustomFields(); + $NamePrefix = "Object-RT::Article-".$ArticleObj->Id."-CustomField-"; +} +else { + $CustomFields = $ClassObj->ArticleCustomFields(); + $NamePrefix = "Object-RT::Article--CustomField-"; +} + +<%ARGS> +$ArticleObj => undef +$ClassObj => undef +$CFContent => undef +$id => undef + diff --git a/rt/share/html/Articles/Article/Elements/EditLinks b/rt/share/html/Articles/Article/Elements/EditLinks new file mode 100644 index 000000000..03b99c8d3 --- /dev/null +++ b/rt/share/html/Articles/Article/Elements/EditLinks @@ -0,0 +1,113 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} + + + + + + + + + + + + +<%ARGS> +$ArticleObj => undef +$id => undef + diff --git a/rt/share/html/Articles/Article/Elements/EditTopics b/rt/share/html/Articles/Article/Elements/EditTopics new file mode 100644 index 000000000..807360bf2 --- /dev/null +++ b/rt/share/html/Articles/Article/Elements/EditTopics @@ -0,0 +1,147 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} + + + +<%INIT> +use Tree::Simple; + +my $inClass = RT::Topics->new($session{'CurrentUser'}); +# global topics should always be available +push @Classes,$RT::System unless grep { $_ == $RT::System } @Classes; +$inClass->LimitToObject($_) for @Classes; +$inClass->OrderByCols({FIELD => 'Name'}); +my $inTree = buildTree($inClass); + +my $otherClass = RT::Topics->new($session{'CurrentUser'}); +if (@Classes) { + $otherClass->Limit(FIELD => 'ObjectType', VALUE => 'RT::Class'); + for (@Classes) { + $otherClass->Limit(FIELD => 'ObjectId', OPERATOR => '!=', VALUE => $_->Id); + } +} else { + $otherClass->UnLimit; +} +my $otherTree = buildTree($otherClass); + +my $articleTopics = RT::ObjectTopics->new($session{'CurrentUser'}); +$articleTopics->LimitToObject($ArticleObj); +my %topics; +while (my $topicObj = $articleTopics->Next) { + $topics{$topicObj->Topic} = 1; +} +$topics{$_} = 1 for @Topics; + +sub buildTree { + my $query = shift; + + use Tree::Simple; + my $tree = Tree::Simple->new(Tree::Simple->ROOT); + my %lookup = (0 => $tree); + + my @todo; + while (my $topic = $query->Next) { + push @todo, $topic; + } + + { + my $changed = 0; + my @work = @todo; + @todo = (); + for my $topic (@work) { + if (defined $lookup{$topic->Parent}) { + $lookup{$topic->Id} = Tree::Simple->new($topic, $lookup{$topic->Parent}); + $changed = 1; + } else { + push @todo, $topic; + } + } + redo unless $changed == 0; + } + return $tree; +} + + +<%ARGS> +$ArticleObj => RT::Article->new($session{'CurrentUser'}) +@Classes => () +@Topics => () +$OnlyThisClass => undef + diff --git a/rt/share/html/Articles/Article/Elements/LinkEntryInstructions b/rt/share/html/Articles/Article/Elements/LinkEntryInstructions new file mode 100644 index 000000000..c2fd1efed --- /dev/null +++ b/rt/share/html/Articles/Article/Elements/LinkEntryInstructions @@ -0,0 +1,49 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} +<&|/l&>Type a: before article numbers and t: before ticket numbers. +<&|/l&>Separate multiple entries with spaces. diff --git a/rt/share/html/Articles/Article/Elements/Preformatted b/rt/share/html/Articles/Article/Elements/Preformatted new file mode 100644 index 000000000..2f0e7869e --- /dev/null +++ b/rt/share/html/Articles/Article/Elements/Preformatted @@ -0,0 +1,127 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} +% if ($include{Name}) { +#<%$Article->Id%>: <%$Article->Name || loc('(no name)')%> +<%'-' x length("#".$Article->Id.": ".($Article->Name || loc('(no name)'))) %> +% } +% if ( $include{Summary} && ($Article->Summary||'') =~ /\S/ ) { +<% $Article->Summary %> +% } +% while (my $cf = $cfs->Next) { +% next unless $include{"CF-Title-".$cf->Id} or $include{"CF-Value-".$cf->Id}; +% my $values = $Article->CustomFieldValues($cf->Id); +% if ($values->Count == 1) { +% my $value = $values->First; +% if ($include{"CF-Title-".$cf->Id}) { +<% $cf->Name%>: +<% '-' x length($cf->Name) %> +% } +% if ($value && $include{"CF-Value-".$cf->Id}) { +<% $get_content->( $value ) %> +% } +% } else { +% my $val = $values->Next; +% if ($include{"CF-Title-".$cf->Id}) { +<% $cf->Name%>: \ +% } +% if ($val && $include{"CF-Value-".$cf->Id}) { +<% $get_content->( $val ) %> +% } +% while ($val = $values->Next) { +% if ($include{"CF-Title-".$cf->Id}) { +<% ' ' x length($cf->Name)%> \ +% } +% if ($include{"CF-Value-".$cf->Id}) { +<% $get_content->( $val ) %> +% } +% } +% } +% } +<%init> +my $class = $Article->ClassObj; +my %include = (Name => 1, Summary => 1); +my $cfs = $class->ArticleCustomFields; +$include{"CF-Title-".$_->Id} = $include{"CF-Value-".$_->Id} = 1 while $_ = $cfs->Next; +$include{$_} = not $class->FirstAttribute("Skip-$_") for keys %include; + +my $de_htmlify = sub { + my $content = shift; + require HTML::TreeBuilder; + my $tree = HTML::TreeBuilder->new; + $tree->parse($content); + $tree->eof(); + + require HTML::FormatText; + my $formatter = HTML::FormatText->new(leftmargin => 0, rightmargin => 50); + $content = $formatter->format($tree); + return $content; +}; + +my $get_content = sub { + my $value = shift; + return '' unless $value; + + my $content = $value->Content; + return '' unless defined $content && length $content; + + $m->callback( + %ARGS, + CallbackName => 'ProcessContent', + content => \$content, + ); + + if ( $content =~ /<.{1,5}>/ ) { + $content = $de_htmlify->( $content ); + } + return $content; +}; + + +<%args> +$Article + diff --git a/rt/share/html/Articles/Article/Elements/SearchByCustomField b/rt/share/html/Articles/Article/Elements/SearchByCustomField new file mode 100644 index 000000000..2a9d14506 --- /dev/null +++ b/rt/share/html/Articles/Article/Elements/SearchByCustomField @@ -0,0 +1,70 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} +%# if the custom field is a select, enumerate the options +% if ($Field->Type =~ /^Select/) { +% my $CustomFieldValues = $Field->ValuesObj(); + +% } +%# otherwise, put in a textedity field +% else { + +% } +<%init> +my @Values =ref( $Values ) ? @{ $Values } : ( $Values ); + +<%ARGS> +$Field => undef +$Name => 'CustomField' +$Values => undef + diff --git a/rt/share/html/Articles/Article/Elements/SelectSavedSearches b/rt/share/html/Articles/Article/Elements/SelectSavedSearches new file mode 100644 index 000000000..c42fae1b5 --- /dev/null +++ b/rt/share/html/Articles/Article/Elements/SelectSavedSearches @@ -0,0 +1,76 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} + + +<%init> +use RT::SavedSearches; +my $groups = $session{'CurrentUser'}->UserObj->OwnGroups; +my %privacies; +$privacies{'RT::User-' . $session{'CurrentUser'}->UserObj->Id} = 1; +map { $privacies{'RT::Group-'.$_->Id} = $_ } @{$groups->ItemsArrayRef}; + + +<%args> +$Name => undef +$Default => undef + diff --git a/rt/share/html/Articles/Article/Elements/SelectSearchPrivacy b/rt/share/html/Articles/Article/Elements/SelectSearchPrivacy new file mode 100644 index 000000000..674a0ffa7 --- /dev/null +++ b/rt/share/html/Articles/Article/Elements/SelectSearchPrivacy @@ -0,0 +1,62 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} + +<%INIT> +my $user = $session{'CurrentUser'}->UserObj; +my $groups = $session{'CurrentUser'}->UserObj->OwnGroups; +$Default = '' unless defined $Default; + +<%ARGS> +$Name => 'GroupField' +$Default => '' + diff --git a/rt/share/html/Articles/Article/Elements/ShowHistory b/rt/share/html/Articles/Article/Elements/ShowHistory new file mode 100644 index 000000000..6ca74bf61 --- /dev/null +++ b/rt/share/html/Articles/Article/Elements/ShowHistory @@ -0,0 +1,76 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} +
- <% $custResolver->AsStringLong |n %> + <% $custResolver->AsStringLong |n %> +%# includes service label and view/svc_ link for cust_svc links
(none) -- cgit v1.2.1 From 3ce70fff14b951189273348f4ddd06aa1069eafc Mon Sep 17 00:00:00 2001 From: Mark Wells Date: Tue, 17 Apr 2012 18:19:05 -0700 Subject: restore agent_custid smart search, #17424 --- FS/FS/cust_main/Search.pm | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/FS/FS/cust_main/Search.pm b/FS/FS/cust_main/Search.pm index 1e9eee79d..31b89cd31 100644 --- a/FS/FS/cust_main/Search.pm +++ b/FS/FS/cust_main/Search.pm @@ -166,6 +166,12 @@ sub smart_search { } } + push @cust_main, qsearch( { + 'table' => 'cust_main', + 'hashref' => { 'agent_custid' => $num, %options }, + 'extra_sql' => " AND $agentnums_sql", #agent virtualization + } ); + if ( $conf->exists('address1-search') ) { my $len = length($num); $num = lc($num); -- cgit v1.2.1 From e39c7a239fe3604445ffdef6472d0e41abca0049 Mon Sep 17 00:00:00 2001 From: Mark Wells Date: Wed, 18 Apr 2012 06:18:14 -0700 Subject: remove ticket links to deleted services, #17067 --- FS/FS/cust_svc.pm | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/FS/FS/cust_svc.pm b/FS/FS/cust_svc.pm index a52791385..6bd8cb837 100644 --- a/FS/FS/cust_svc.pm +++ b/FS/FS/cust_svc.pm @@ -98,6 +98,28 @@ Deletes this service from the database. If there is an error, returns the error, otherwise returns false. Note that this only removes the cust_svc record - you should probably use the B method instead. +=cut + +sub delete { + my $self = shift; + my $error = $self->SUPER::delete; + return $error if $error; + + if ( FS::Conf->new->config('ticket_system') eq 'RT_Internal' ) { + FS::TicketSystem->init; + my $session = FS::TicketSystem->session; + my $links = RT::Links->new($session->{CurrentUser}); + my $svcnum = $self->svcnum; + $links->Limit(FIELD => 'Target', + VALUE => 'freeside://freeside/cust_svc/'.$svcnum); + while ( my $l = $links->Next ) { + my ($val, $msg) = $l->Delete; + # can't do anything useful on error + warn "error unlinking ticket $svcnum: $msg\n" if !$val; + } + } +} + =item cancel Cancels the relevant service by calling the B method of the associated -- cgit v1.2.1 From c9d57a5a0083a91bc5d1427b6198bd7ee894cad1 Mon Sep 17 00:00:00 2001 From: Mark Wells Date: Wed, 18 Apr 2012 16:37:23 -0700 Subject: fix positioning in cust_msg display, #16189 --- httemplate/view/cust_msg.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/httemplate/view/cust_msg.html b/httemplate/view/cust_msg.html index ec584605d..67ceef799 100755 --- a/httemplate/view/cust_msg.html +++ b/httemplate/view/cust_msg.html @@ -22,7 +22,7 @@ function toggle_display(obj) { Body
+

+ + + + + + + +<%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 title' => ['div#header h1']], + ['Page content' => ['div#body']], + ['Buttons' => ['input[type="reset"], input[type="submit"], input[class="button"]']], + ['Button hover' => ['input[type="reset"]:hover, input[type="submit"]:hover, input[class="button"]:hover']], +); + + +<%INIT> +unless ($session{'CurrentUser'}->HasRight( Object=> RT->System, Right => 'SuperUser')) { + Abort(loc('This feature is only available to system administrators.')); +} + +use Digest::MD5 'md5_hex'; + +my $text_threshold = 0.6; +my @results; +my $imgdata; + +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}), + } ); + push @results, loc("Unable to set UserLogo: [_1]", $msg) unless $id; + + $imgdata = $file_hash->{LargeContent}; +} +elsif ($ARGS{'reset_logo'}) { + RT->System->DeleteAttribute('UserLogo'); +} +else { + if (my $attr = RT->System->FirstAttribute('UserLogo')) { + my $content = $attr->Content; + if (ref($content) eq 'HASH') { + $imgdata = $content->{data}; + } + else { + RT->System->DeleteAttribute('UserLogo'); + } + } +} + +if ($user_css) { + if ($ARGS{'reset_css'}) { + RT->System->DeleteAttribute('UserCSS'); + undef $user_css; + } + else { + my ($id, $msg) = RT->System->SetAttribute( Name => "UserCSS", + Description => "User-provided css", + Content => $user_css ); + push @results, loc("Unable to set UserCSS: [_1]", $msg) unless $id; + } +} + +if (!$user_css) { + my $attr = RT->System->FirstAttribute('UserCSS'); + $user_css = $attr ? $attr->Content : join( + "\n\n" => map { + join "\n" => "/* ". $_->[0] ." */", + map { "$_ {}" } @{$_->[1]} + } @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) { + warn "bad"; + } + return \@top5; +} + +<%ARGS> +$user_css => '' + diff --git a/rt/share/html/Articles/Article/Delete.html b/rt/share/html/Articles/Article/Delete.html new file mode 100644 index 000000000..7abd824d5 --- /dev/null +++ b/rt/share/html/Articles/Article/Delete.html @@ -0,0 +1,106 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} +<& /Elements/Header, Title => $title &> +<& /Elements/Tabs &> + +% if ($ARGS{'Delete'}) { +<%$title%> +<& /Elements/ListActions, actions => \@results &> + +% } else { +<&|/l&>Are you sure you want to delete this article? + + + + + + +
+
+ + +
+ +
+
+ + + +
+
+% } +<%INIT> + +my @results; + +my $title; +my $ArticleObj = RT::Article->new( $session{'CurrentUser'} ); + + +$ArticleObj->Load($id); +unless ( $ArticleObj->id ) { + $m->comp("/Elements/Error", Why => loc("Unable to load article") ); +} + + +unless ( $ArticleObj->CurrentUserHasRight('ModifyArticle') ) { + $m->comp("/Elements/Error", Why => loc("No permission to modify article")); +} + +if ($ARGS{'Delete'} eq 'yes') { + $ArticleObj->Delete(); + $title = loc('Article #[_1] deleted', $ArticleObj->Id); +} + +else { + $title = loc('Delete article #[_1]', $ArticleObj->Id); +} + +<%ARGS> +$id => undef + diff --git a/rt/share/html/Articles/Article/Display.html b/rt/share/html/Articles/Article/Display.html new file mode 100644 index 000000000..b80dc1c5e --- /dev/null +++ b/rt/share/html/Articles/Article/Display.html @@ -0,0 +1,92 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} +<& /Elements/Header, Title => $title &> +<& /Elements/Tabs &> +

<&|/l&>Basics

+<&|/l&>Class: <%$article->ClassObj->Name%>
+<%$article->Summary%> +

<&|/l&>Content

+<& /Elements/ShowCustomFields, Object => $article &> + +

<&|/l&>Links

+<& Elements/ShowLinks, article => $article &> + +

<&|/l&>Topics

+<& Elements/ShowTopics, article => $article &> +<%init> + +my $article = RT::Article->new( $session{'CurrentUser'} ); +if ($Name) { + $article->LoadByCols( Name => $Name ); +} +elsif ($id) { + $article->Load($id); +} +unless ( $article->Id ) { + if ( $ARGS{'Name'} ) { + $m->comp( 'Edit.html', %ARGS ); + return (); + } + else { + $m->comp( "/Elements/Error", Why => loc("Article not found") ); + } + +} + +unless ( $article->CurrentUserHasRight('ShowArticle') ) { + $m->comp( "/Elements/Error", Why => loc("Permission Denied") ); +} +my $title = loc( "Article #[_1]: [_2]", $article->Id, $article->Name || loc("(no name)")); + +$id = $article->id; + + +<%args> +$id => undef +$Name => undef + diff --git a/rt/share/html/Articles/Article/Edit.html b/rt/share/html/Articles/Article/Edit.html new file mode 100644 index 000000000..756aa2cc9 --- /dev/null +++ b/rt/share/html/Articles/Article/Edit.html @@ -0,0 +1,333 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} +<& /Elements/Header, Title => $title &> +<& /Elements/Tabs &> +<& /Elements/ListActions, actions => \@results &> + +
+ + + + + + + +<& Elements/EditBasics, ArticleObj => $ArticleObj, + EditClass =>$EditClass, + ClassObj => $ClassObj, + %ARGS , + id => $id + &> + + + + + +<& Elements/EditCustomFields, ArticleObj => $ArticleObj, + CFContent => \%CFContent, + ClassObj => $ClassObj, + %ARGS, + id =>$id, + &> + + + + + +<& Elements/EditLinks, ArticleObj => $ArticleObj, + %ARGS, + id => $id + &> + + + + + + + + +

<&|/l&>Basics

<&|/l&>Content

<&|/l&>Links

<&|/l&>Topics

<&|/l&>Topics +<& Elements/EditTopics, ArticleObj => $ArticleObj, + Classes => [$ArticleObj->Id ? $ArticleObj->ClassObj : $ClassObj], + OnlyThisClass => 1, + %ARGS, + id => $id + &> +
+<& /Elements/Submit, Label => ($id eq 'new' ? loc('Create') : loc('Save Changes')), color => "#993333" &> +
+ +<%INIT> + +if ( exists $ARGS{'Topics'} ) { + $ARGS{'Topics'} = + ref( $ARGS{'Topics'} ) ? $ARGS{'Topics'} : [ $ARGS{'Topics'} ]; +} + +my @results; +my $title; + +my $Entries = {}; +my $ArticleObj = RT::Article->new( $session{'CurrentUser'} ); +my $ClassObj = RT::Class->new( $session{'CurrentUser'} ); +my %create_args; +my %CFContent; +my $EditClass = 1; +if ( !$id ) { + $title = loc('Create a new article'); + foreach my $arg ( sort keys %ARGS ) { + if ( $arg =~ /^Transaction-(\d+)$/ ) { + my $trans = RT::Transaction->new( $session{'CurrentUser'} ); + $trans->Load($1); + $CFContent{ $ARGS{$arg} } .= "\n\n" if $CFContent{ $ARGS{$arg} }; + $CFContent{ $ARGS{$arg} } .= $trans->Content; + } + } + + $ClassObj->Load($Class); + unless ( $ClassObj->Id ) { + $m->comp( "/Elements/Error", + Why => loc( "'[_1]' isn't a valid class identifier", $Class ) ); + } + $EditClass = 0; + $id = 'new'; +} +elsif ( $id eq 'new' ) { + + if ( $ARGS{'RefersTo-new'} ) { + @{ $create_args{'RefersTo-new'} } = + split( /\s+/, $ARGS{'RefersTo-new'} ); + } + + if ( $ARGS{'new-RefersTo'} ) { + @{ $create_args{'new-RefersTo'} } = + split( /\s+/, $ARGS{'new-RefersTo'} ); + } + + + foreach my $arg (keys %ARGS) { + next if $arg =~ /-(?:Magic|Category)$/; + # Object-RT::Article--CustomField-3-Values + if ( $arg =~ /^Object-RT::Article--CustomField-(\d+)(.*?)$/ ) { + my $cfid = $1; + + my $cf = RT::CustomField->new( $session{'CurrentUser'} ); + $cf->Load( $cfid ); + unless ( $cf->id ) { + $RT::Logger->error( "Couldn't load custom field #". $cfid ); + next; + } + + if ( $arg =~ /-Upload$/ ) { + $create_args{"CustomField-$cfid"} = _UploadedFile( $arg ); + next; + } + + my $type = $cf->Type; + + my @values = (); + if ( ref $ARGS{ $arg } eq 'ARRAY' ) { + @values = @{ $ARGS{ $arg } }; + } elsif ( $type =~ /text/i ) { + @values = ($ARGS{ $arg }); + } else { + @values = split /\r*\n/, $ARGS{ $arg } || ''; + } + @values = grep $_ ne '', + map { + s/\r+\n/\n/g; + s/^\s+//; + s/\s+$//; + $_; + } + grep defined, @values; + + $create_args{"CustomField-$cfid"} = \@values; + } + } + + my $msg; + ( $id, $msg ) = $ArticleObj->Create( + Summary => $ARGS{'Summary'}, + Name => $ARGS{'Name'}, + Class => $ARGS{'Class'}, + Topics => $ARGS{'Topics'}, + %create_args + ); + push( @results, $msg ); + if ($id) { + + + $ArticleObj->Load($id); + + $title = loc( 'Modify article #[_1]', $ArticleObj->Id ); + delete $ARGS{id}; + + if ( $ARGS{next} ) { + $m->redirect($ARGS{next}); + } + else { + MaybeRedirectForResults( + Actions => \@results, + Arguments => { id => $ArticleObj->id }, + ); + } + } + if (!$id) { + $ClassObj->Load($Class); + unless ( $ClassObj->Id ) { + $m->comp( "/Elements/Error", + Why => loc( "'[_1]' isn't a valid class identifier", $Class ) ); + } + $ArticleObj = RT::Article->new( $session{'CurrentUser'} ); + $id = 'new'; + $EditClass = 0; + $title = loc('Create a new article'); + } +} +else { + + $ArticleObj->Load($id); + unless ( $ArticleObj->id ) { + $m->comp( "/Elements/Error", + Why => loc("Unable to load article") ); + } + + my @attribs = qw(Name Summary Class); + + @results = UpdateRecordObject( + AttributesRef => \@attribs, + Object => $ArticleObj, + ARGSRef => \%ARGS + ); + + my @cf_results = ProcessObjectCustomFieldUpdates( + Object => $ArticleObj, + ARGSRef => \%ARGS + ); + @results = ( @results, @cf_results ); + + # Delete links that are gone gone gone. + foreach my $arg ( keys %ARGS ) { + if ( $arg =~ /DeleteLink-(.*?)-(RefersTo|MemberOf|RefersTo)-(.*)$/ ) { + my $base = $1; + my $type = $2; + my $target = $3; + + my ( $val, $msg ) = $ArticleObj->DeleteLink( + Base => $base, + Type => $type, + Target => $target + ); + + push @results, $msg; + + } + + } + + my @linktypes = qw(DependsOn MemberOf RefersTo ); + + foreach my $linktype (@linktypes) { + + for my $luri ( split( / /, ( $ARGS{ $ArticleObj->Id . "-$linktype" } || '' )) ) { + $luri =~ s/\s*$//; # Strip trailing whitespace + my ( $val, $msg ) = + $ArticleObj->AddLink( Target => $luri, Type => $linktype ); + push @results, $msg; + delete $ARGS{ $ArticleObj->Id . "-$linktype" } if $val; + } + + for my $luri ( split( / /, ( $ARGS{ "$linktype-" . $ArticleObj->Id } || '' )) ) { + my ( $val, $msg ) = + $ArticleObj->AddLink( Base => $luri, Type => $linktype ); + push @results, $msg; + delete $ARGS{ "$linktype-" . $ArticleObj->Id } if $val; + } + + } + + my %topics; + if ( $ARGS{'EditTopics'} ) { + $topics{$_}++ for @{ $ARGS{'Topics'} }; + my $objTopics = + RT::ObjectTopics->new( $session{'CurrentUser'} ); + $objTopics->LimitToObject($ArticleObj); + while ( my $t = $objTopics->Next ) { + $topics{ $t->Topic }--; + } + for my $id ( keys %topics ) { + if ( $topics{$id} > 0 ) { + my ( $val, $msg ) = $ArticleObj->AddTopic( Topic => $id ); + push @results, $msg; + } + elsif ( $topics{$id} < 0 ) { + my ( $val, $msg ) = $ArticleObj->DeleteTopic( Topic => $id ); + push @results, $msg; + } + } + } + + $title = loc( 'Modify article #[_1]', $ArticleObj->Id ); +} + +# if they're working on an existing article +if ( $ArticleObj->id ) { + unless ( $ArticleObj->CurrentUserHasRight('ShowArticle') ) { + $m->comp( "/Elements/Error", + Why => loc("No permission to view Article") ); + } +} + + + + +<%ARGS> +$id => undef +$Class => undef + diff --git a/rt/share/html/Articles/Article/Elements/EditBasics b/rt/share/html/Articles/Article/Elements/EditBasics new file mode 100644 index 000000000..256d81610 --- /dev/null +++ b/rt/share/html/Articles/Article/Elements/EditBasics @@ -0,0 +1,73 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} +
<&|/l&>Name
<&|/l&>Summary
<&|/l&>Class +% if ($EditClass) { +<& /Articles/Elements/SelectClass, Name => 'Class', Default =>$ArticleObj->ClassObj->Id&> +% } else { +<%$ClassObj->Name%> + +% } +
<%$CustomField->Name%>
<%$CustomField->FriendlyType%>
<& /Elements/EditCustomField, + Object => $ArticleObj, + CustomField => $CustomField, + NamePrefix => $NamePrefix, + Default => + ($CFContent->{$CustomField->Id} || + $ARGS{$NamePrefix .$CustomField->id .'-Values'} || + $ARGS{$NamePrefix .$CustomField->id .'-Value'}) + , + Rows => 15, + Cols => 70 + &>
<&|/l&>Enter articles, tickets, or other URLs related to this article. +<& LinkEntryInstructions &> +% unless ($id eq 'new') { +<&|/l&>(Check boxes to delete)
+% } +
<&|/l&>Refers to:
+
    +% if ($id ne 'new') { +% my $refersto = $ArticleObj->RefersTo; +% while (my $link = $refersto->Next) { +% my $member = $link->TargetURI; +
  • + +% if ($link->TargetURI->IsLocal) { +<% loc($member->Object->ObjectTypeStr) %> <%$member->Object->Id%>: +% if (UNIVERSAL::isa($member->Object, "RT::Article") or UNIVERSAL::can($member->Object, 'Name')) { +<%$member->Object->Name%> +% } elsif (UNIVERSAL::isa($member->Object, "RT::Ticket") or UNIVERSAL::can($member->Object, 'Subject')) { +<%$member->Object->Subject%> +% } + +% } else { +<%$link->Target%> +% } +% } +% } +
+
<&|/l&>Referred to by: +
+ +
+% my $i; +% while (my $transaction = $transactions->Next) { + + + + + +% } +
<%$transaction->CreatedObj->AsString%><%$transaction->CreatorObj->Name%><%$transaction->Description%>
+<%init> + +my $article = RT::Article->new($session{'CurrentUser'}); + +$article->Load($id); +unless ($article->Id) { + $m->comp("/Elements/Error", Why => loc("Article not found")); +} + +unless ($article->ClassObj->CurrentUserHasRight('ShowArticle')) { + $m->comp("/Elements/Error", Why => loc("Permission Denied")); +} + +my $transactions = $article->Transactions(); + + +<%args> +$id => undef + diff --git a/rt/share/html/Articles/Article/Elements/ShowLinks b/rt/share/html/Articles/Article/Elements/ShowLinks new file mode 100644 index 000000000..2e48ac949 --- /dev/null +++ b/rt/share/html/Articles/Article/Elements/ShowLinks @@ -0,0 +1,92 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} +<&|/l&>Refers to:
+ + +<&|/l&>Referred to by:
+ +<%args> +$article => undef + diff --git a/rt/share/html/Articles/Article/Elements/ShowSavedSearches b/rt/share/html/Articles/Article/Elements/ShowSavedSearches new file mode 100644 index 000000000..8ced74b1c --- /dev/null +++ b/rt/share/html/Articles/Article/Elements/ShowSavedSearches @@ -0,0 +1,85 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} +<& /Elements/TitleBoxStart, title => loc('Saved searches') &> +%# Keep track of what our current search ID is. + +%# Hide all the save functionality if the user shouldn't see it. +% if ($session{'CurrentUser'}->HasRight( Right => 'CreateSavedSearch', +% Object=> $RT::System )) { +

<&|/l&>Save this search

+<&|/l&>Name: +<&|/l&>Privacy: <& SelectSearchPrivacy, Name => 'SearchPrivacy', + Default => $Privacy &>
+% if ($CurrentSearch && $CurrentSearch ne 'new') { +  +  +  +% } else { + +% } +
+% } # if HasRight 'CreateSavedSearch' + +

<&|/l&>Load a saved search

+<& SelectSavedSearches, Name => 'LoadSavedSearch', Default => $CurrentSearch &> + +<& /Elements/TitleBoxEnd &> + +<%INIT> +unless ($session{'CurrentUser'}->HasRight( Right => 'LoadSavedSearch', + Object=> $RT::System )) { + return; +} + + + +<%ARGS> +$CurrentSearch => undef +$Name => undef +$Privacy => undef + diff --git a/rt/share/html/Articles/Article/Elements/ShowSearchCriteria b/rt/share/html/Articles/Article/Elements/ShowSearchCriteria new file mode 100644 index 000000000..377cdb1f0 --- /dev/null +++ b/rt/share/html/Articles/Article/Elements/ShowSearchCriteria @@ -0,0 +1,171 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} +% if ($ARGS{'HideOptions'}) { +<& /Elements/TitleBoxStart, title => loc('Advanced search'), class => "rolled-up", bodyclass => "hidden" &> +% } else { +<& /Elements/TitleBoxStart, title => loc('Advanced search') &> +% } + + + + + + + + + + + + + + + + + + + + + +% while (my $field = $customfields->Next ) { + + + + +% } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

<&|/l&>Basics

<&|/l&>Classis <& /Articles/Elements/SelectClass, Name => 'Class', Multiple =>1, Size => 5 , ShowNullOption => undef, Default => $ARGS{'Class'} &> +<&|/l&>and not +<& /Articles/Elements/SelectClass, Name => 'Class!', Multiple =>1, Size => 5 , ShowNullOption => undef, Default => $ARGS{'Class!'} &>
<&|/l&>Name<&|/l&>matches <&|/l&>and not
<&|/l&>Summary<&|/l&>matches <&|/l&>and not

<&|/l&>Content

<&|/l&>Any field <&|/l&>matches <&|/l&>and not
<% $field->Name %><&|/l&>matches +% my $matches = $field->Name."~"; +% my $nomatches = $field->Name."!~"; +<& /Articles/Article/Elements/SearchByCustomField, + Field => $field, + Name => $matches, + Values => $ARGS{$matches} &> + <&|/l&>and not +<& /Articles/Article/Elements/SearchByCustomField, + Field => $field, + Name => $nomatches, + Values => $ARGS{$nomatches} + &> +

<&|/l&>Dates

<&|/l&>Created<&|/l&>after +<& /Elements/SelectDate, Name=>"Created>", Default => ($dates->{'Created>'} ? $dates->{'Created>'}->ISO : '') &> +<&|/l&>and before +<& /Elements/SelectDate, Name=>"Created<", Default => ($dates->{'Created<'} ? $dates->{'Created<'}->ISO:'')&> +
<&|/l&>Last updated<&|/l&>after +<& /Elements/SelectDate, Name=>"LastUpdated>", Default => +($dates->{'LastUpdated>'} ? $dates->{'LastUpdated>'}->AsString:'')&> +<&|/l&>and before +<& /Elements/SelectDate, Name=>"LastUpdated<", Default => +($dates->{'LastUpdated<'} ? $dates->{'LastUpdated<'}->AsString:'')&> +

<&|/l&>Links

<& LinkEntryInstructions &>
<&|/l&>Refer to
<&|/l&>Referred to by

<&|/l&>Topics

+<& /Articles/Article/Elements/EditTopics, %ARGS, Classes => \@Classes, OnlyThisClass => 1 &> +
+ /> +<&|/l&>Include subtopics +
+<& /Elements/Submit, Label => loc('Search') &> +<&/Elements/TitleBoxEnd&> +<%init> +my @Classes = + ( ref $ARGS{'Class'} eq 'ARRAY' ) + ? @{ $ARGS{'Class'} } + : ( $ARGS{'Class'} ); +for (@Classes) { + my $class = RT::Class->new( $session{'CurrentUser'} ); + $class->LoadById($_); + $_ = $class; +} + +for my $field ( qw/Class Name Summary Article/ ) { + $ARGS{"$field~"} = '' unless defined $ARGS{"$field~"}; + $ARGS{"$field!~"} = '' unless defined $ARGS{"$field!~"}; +} +$RefersTo = '' unless defined $RefersTo; +$ReferredToBy = '' unless defined $ReferredToBy; + + + +<%ARGS> +$dates =>undef +$RefersTo => '' +$ReferredToBy => '' +$customfields => undef + diff --git a/rt/share/html/Articles/Article/Elements/ShowTopics b/rt/share/html/Articles/Article/Elements/ShowTopics new file mode 100644 index 000000000..31aae36eb --- /dev/null +++ b/rt/share/html/Articles/Article/Elements/ShowTopics @@ -0,0 +1,58 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} +% my $topics = RT::ObjectTopics->new($session{'CurrentUser'}); +% $topics->LimitToObject($article); +% my @topics; +% while (my $t = $topics->Next) { +<& /Articles/Elements/ShowTopic, topic => $t->TopicObj &>
+% } +
+ +<%args> +$article => undef + diff --git a/rt/share/html/Articles/Article/ExtractFromTicket.html b/rt/share/html/Articles/Article/ExtractFromTicket.html new file mode 100644 index 000000000..5d9eba2fc --- /dev/null +++ b/rt/share/html/Articles/Article/ExtractFromTicket.html @@ -0,0 +1,105 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} +<& /Elements/Header, Title => loc('Extract article from ticket #[_1] into class [_2]',$Ticket, $ClassObj->Name) &> +<& /Elements/Tabs &> +
+ + +% for (@Topics) { + +% } + + +

<&|/l&>Use the dropdown menus to select which ticket updates you want to extract into a new article. +<&|/l&>You can insert ticket content into any freeform, text or wiki field. +

+ + + + +% my $i; +% while ( my $trans = $transactions->Next ) { +% next unless $trans->Content; + + + + +% } +
<&|/l&>Field<&|/l&>Ticket update
+ +<%$trans->CreatedObj->AsString%>: <%$trans->Description%>
+
<%$trans->Content%>
+
+<& /Elements/Submit, Label => loc('Create'), color => "#993333" &> +
+<%INIT> + +my $ticket=LoadTicket($Ticket); +my $transactions = $ticket->Transactions; + +my $ClassObj = RT::Class->new($session{'CurrentUser'}); +$ClassObj->Load($Class); +unless ($ClassObj->Id) { + $m->comp("/Elements/Error", Why => loc("'[_1]' isn't a valid class identifier", $Class)); +} +my $CustomFields = $ClassObj->ArticleCustomFields(); + +$CustomFields->Limit(FIELD => 'Type', OPERATOR => '=', VALUE => 'Text'); +$CustomFields->Limit(FIELD => 'Type', OPERATOR => '=', VALUE => 'Wikitext'); +$CustomFields->Limit(FIELD => 'Type', OPERATOR => '=', VALUE => 'Freeform'); + +<%ARGS> +$Class => undef +$Ticket => undef +@Topics => () + diff --git a/rt/share/html/Articles/Article/ExtractIntoClass.html b/rt/share/html/Articles/Article/ExtractIntoClass.html new file mode 100644 index 000000000..adf23fc0f --- /dev/null +++ b/rt/share/html/Articles/Article/ExtractIntoClass.html @@ -0,0 +1,76 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} +<& /Elements/Header, Title => loc('Extract a new article from ticket #[_1]',$Ticket) &> +<& /Elements/Tabs &> + + +

<&|/l&>Create a new article in:

+
    +% my $Classes = RT::Classes->new($session{'CurrentUser'}); +% $Classes->LimitToEnabled(); +% while (my $Class = $Classes->Next) { +
  • <%$Class->Name%>: +<%$Class->Description%> + +
  • +% } +
+<%args> +$Ticket => undef + diff --git a/rt/share/html/Articles/Article/ExtractIntoTopic.html b/rt/share/html/Articles/Article/ExtractIntoTopic.html new file mode 100644 index 000000000..72fd32464 --- /dev/null +++ b/rt/share/html/Articles/Article/ExtractIntoTopic.html @@ -0,0 +1,72 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} +<& /Elements/Header, Title => loc('Extract a new article from ticket #[_1]',$Ticket) &> +<& /Elements/Tabs &> + + +<&|/l&>Select topics for this article:
+
+ + +<& Elements/EditTopics, Classes => [$ClassObj], + OnlyThisClass => 1, + id => 'new', + &>
+ +
+<%args> +$Ticket => undef +$Class => undef + +<%init> +my $ClassObj = RT::Class->new($session{'CurrentUser'}); +$ClassObj->Load($Class); +unless ($ClassObj->Id) { + $m->comp("/Elements/Error", Why => loc("'[_1]' isn't a valid class identifier", $Class)); +} + diff --git a/rt/share/html/Articles/Article/History.html b/rt/share/html/Articles/Article/History.html new file mode 100644 index 000000000..1c2873f18 --- /dev/null +++ b/rt/share/html/Articles/Article/History.html @@ -0,0 +1,57 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} +<& /Elements/Header, Title => $title &> +<& /Elements/Tabs &> +<& Elements/ShowHistory, id => $id &> +<%init> +my $title =loc('History for article #[_1]',$id); + + +<%args> +$id => undef + diff --git a/rt/share/html/Articles/Article/PreCreate.html b/rt/share/html/Articles/Article/PreCreate.html new file mode 100644 index 000000000..49507d4a8 --- /dev/null +++ b/rt/share/html/Articles/Article/PreCreate.html @@ -0,0 +1,62 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} +<& /Elements/Header, Title => loc('Create an article in class...') &> +<& /Elements/Tabs, Title => loc('Create an article in class...') &> +
    +% my $Classes = RT::Classes->new($session{'CurrentUser'}); +% $Classes->LimitToEnabled(); +% my $have_classes = 0; +% while (my $Class = $Classes->Next) { +% $have_classes++; +% my $qs = $m->comp("/Elements/QueryString", %ARGS, Class=> $Class->Id); +
  • <&|/l, $Class->Name &>in class [_1]
  • +% } +
+% unless ( $have_classes ) { +<&|/l&>Permission Denied +% } diff --git a/rt/share/html/Articles/Article/Search.html b/rt/share/html/Articles/Article/Search.html new file mode 100644 index 000000000..f995d41a7 --- /dev/null +++ b/rt/share/html/Articles/Article/Search.html @@ -0,0 +1,269 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} +<& /Elements/Header, Title => loc("Search for articles") &> +<& /Elements/Tabs &> + +% unless ( keys %ARGS ) { +% my $Classes = RT::Classes->new($session{'CurrentUser'}); +% $Classes->LimitToEnabled(); + + + + + +
+ + +
+<& /Elements/TitleBoxStart, title => loc('Saved searches') &> +<&|/l&>Load saved search:
+<& Elements/SelectSavedSearches, Name => 'LoadSavedSearch', Default => $CurrentSearch &> + +<& /Elements/TitleBoxEnd &> +
+
+% return; +% } + +<& /Elements/ListActions, actions => \@results &> + + +% if ($articles->BuildSelectCountQuery =~ /WHERE/i) { +

<&|/l&>Search results

+<& /Elements/CollectionList, + Collection => $articles, + AllowSorting => 1, + OrderBy => \@OrderBy, + Order => \@Order, + Format => $format, + GenericQueryArgs => { %filtered, Format => $format, }, + &> +% } + +
+
+
+ +
+<& Elements/ShowSearchCriteria, dates => \%dates, RefersTo => $RefersTo, customfields => $customfields, ReferredToBy => $ReferredToBy, %ARGS &> +
+
+<& Elements/ShowSavedSearches, CurrentSearch => $CurrentSearch, + Name => ($search ? $search->Name : undef), + Privacy => ($search ? $search->Privacy : undef) &> + +
+ + +<%init> +use RT::SavedSearch; +my @results; +my $articles = RT::Articles->new( $session{'CurrentUser'} ); +my $format = q{ + '__id__/TITLE:#', + '__Name__/TITLE:Name', + '__ClassName__', + '__CreatedRelative__', + '__LastUpdatedRelative__', + '__Summary__', + '__Topics__', }; + +# {{{ Quicksearch logic + +# If it is a number, load the article with that ID. Otherwise, search +# on name and summary. +if ($ARGS{'q'} && $ARGS{'q'} =~ /^(\d+)$/) { + return $m->comp("/Articles/Article/Display.html", id => $1); +} +# }}} + +# {{{ Saved search logic + +my $search; + +# The keys in %ARGS that are not saved and loaded with named searches. +# These need to be treated specially. +my @metakeys = qw/NewSearchName CurrentSearch SearchPrivacy Save Load + Update Delete/; + +if ($CurrentSearch =~ /^(.*-\d+)-SavedSearch-(\d+)$/) { + $search = RT::SavedSearch->new($session{'CurrentUser'}); + $search->Load($1, $2); +} + +# Have we been asked to load a search? + +if ($ARGS{'Load'}) { + if ($ARGS{'LoadSavedSearch'} =~ /^(.*-\d+)-SavedSearch-(\d+)$/ ) { + my $privacy = $1; + my $search_id = $2; + + $search = RT::SavedSearch->new($session{'CurrentUser'}); + my ($ret, $msg) = $search->Load($privacy, $search_id); + if ($ret) { + my $searchargs = $search->GetParameter('args'); + # Clean out ARGS and fill it in with the saved args from the + # loaded search. + foreach my $key (@metakeys) { + $searchargs->{$key} = $ARGS{$key}; + } + %ARGS = %{$searchargs}; + $CurrentSearch = "$privacy-SavedSearch-$search_id"; + } else { + push(@results, loc("Error: could not load saved search [_1]: [_2]", + $ARGS{'LoadSavedSearch'}, $msg)); + } + } else { + push(@results, loc("Invalid [_1] argument", 'LoadSavedSearch')); + } +} + +# ...or have we been asked to save, update, or delete a search? + +if ($ARGS{'Save'}) { + my %searchargs = %ARGS; + foreach my $key (@metakeys) { + delete $searchargs{$key}; + } + + $search = RT::SavedSearch->new($session{'CurrentUser'}); + unless ($ARGS{'SearchPrivacy'} =~ /^(.*)-(\d+)$/) { + # This shouldn't really happen, but hey. + push(@results, loc("WARNING: Saving search to user-level privacy")); + $ARGS{'SearchPrivacy'} = 'RT::User-'.$session{'CurrentUser'}->Id; + } + my ($ret, $msg) = $search->Save(Privacy => $ARGS{'SearchPrivacy'}, + Type => 'Article', + Name => $ARGS{'NewSearchName'}, + SearchParams => {'args' => \%searchargs}); + if ($ret) { + $CurrentSearch = $ARGS{'SearchPrivacy'} . "-SavedSearch-" . + $search->Id; + push(@results, loc("Created search [_1]", $search->Name)); + } else { + undef $search; # if we bomb out creating a search + # we don't want to have the empty object hang around + push(@results, loc("Could not create search: [_1]", $msg)); + } +} elsif ($ARGS{'Update'}) { + if ($ARGS{'SearchPrivacy'} != $search->Privacy) { + push(@results, + loc("Error: cannot change privacy value of existing search")); + } else { + my %searchargs = %ARGS; + foreach my $key (@metakeys) { + delete $searchargs{$key}; + } + + # We already have a search loaded, because CurrentSearch is set, + # or else we would not have gotten here. + my ($ret, $msg) = $search->Update(Name => $ARGS{'NewSearchName'}, + SearchParams => \%searchargs); + if ($ret) { + push(@results, loc("Search [_1] updated", $search->Name)); + } else { + push(@results, loc("Error: search [_1] not updated: [_2]", + $search->Name, $msg)); + } + } +} elsif ($ARGS{'Delete'}) { + # Keep track of this, as we are about to delete the search. + my $searchname = $search->Name; + my ($ret, $msg) = $search->Delete; + if ($ret) { + $ARGS{'CurrentSearch'} = undef; + push(@results, loc("Deleted search [_1]", $searchname)); + # Get rid of all the state. + foreach my $key (keys %ARGS) { + delete $ARGS{$key}; + } + $CurrentSearch = 'new'; + $search = undef; + $RefersTo = undef; + $ReferredToBy = undef; + } else { + push(@results, loc("Could not delete search [_1]: [_2]", + $searchname, $msg)); + } +} + +# }}} + + # Don't want to search for a null class when there is no class specced +my $customfields = RT::CustomFields->new( $session{'CurrentUser'} ); +my %dates; + +$articles->Search( %ARGS, CustomFields => $customfields, Dates => \%dates, + OrderBy => \@OrderBy, Order => \@Order, ); + +$m->callback( %ARGS, _Search => $articles ); + +my %filtered = %ARGS; +delete $filtered{$_} for (@metakeys, "EditTopics", "ExpandTopics"); +delete $filtered{$_} for grep {$filtered{$_} !~ /\S/} keys %filtered; +@filtered{qw(OrderBy Order)} = (\@OrderBy, \@Order); +my $QueryString = "?".$m->comp('/Elements/QueryString', %filtered); + + +<%ARGS> +$CreatedBefore => '' +$CreatedAfter => '' +$LastUpdatedBefore => '' +$LastUpdatedAfter => '' +$RefersTo => undef +$ReferredToBy => undef +$CurrentSearch => 'new' +@OrderBy => () +@Order => () + diff --git a/rt/share/html/Articles/Elements/BeforeMessageBox b/rt/share/html/Articles/Elements/BeforeMessageBox new file mode 100644 index 000000000..8ed04513f --- /dev/null +++ b/rt/share/html/Articles/Elements/BeforeMessageBox @@ -0,0 +1,239 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} +% if ( $ARGS{id} && $ARGS{id} ne 'new' ) { + +% } + + +% unless (RT->Config->Get('HideArticleSearchOnReplyCreate')) { + + + + + + + + + +% } +% if ($hotlist->Count) { + + + + + +% } +% my %dedupe_articles; +% while (my $article = $articles_content->Next) { +% $dedupe_articles{$article->Id}++; + + + + + +% } +% while (my $article = $articles_basics->Next) { +% next if $dedupe_articles{$article->Id}; + + + + + +% } +% if ( @$topics ) { + + + + + + +% if ( $ARGS{$name_prefix .'Articles-Include-Topic'} ) { + + + + + + +% } +% } + + +
<&|/l&>Search for Articles matching
<&|/l&>Include Article:
<&|/l&>Select an Article to include +
 <%$article->Name|| loc('(no name)')%>: <%$article->Summary%>
 <%$article->Name || loc('(no name)')%>: <%$article->Summary || ''%>
+<&|/l, $QueueObj->Name &>Choose from Topics for [_1] + + +
+<&|/l, $included_topic->Name &>Select an Article from [_1] + + +
+ +<%init> +my $QueueObj = $ARGS{QueueObj}; +if ( $ARGS{id} && $ARGS{id} ne 'new' && !$QueueObj ) { + my $ticket = RT::Ticket->new( $session{CurrentUser} ); + $ticket->Load( $ARGS{id} ); + $QueueObj = $ticket->QueueObj; +} + +my $skip = 0; +$m->callback(CallbackName => "Init", skip => \$skip, Queue => $QueueObj); +return if $skip; + +my $name_prefix = ''; +if ( $ARGS{'MessageBoxName'} ) { + $name_prefix = $ARGS{'MessageBoxName'} .'-'; +} + +# convert Articles-Include-Article => $id to Articles-Include-Article-$id +if ( my $tmp = $ARGS{$name_prefix ."Articles-Include-Article"} ) { + $ARGS{$name_prefix ."Articles-Include-Article-$tmp"}++; +} + +my %uri; +if ( $ARGS{id} && $ARGS{id} ne 'new' ) { + $uri{$_}++ for split ' ', ($ARGS{$ARGS{'id'}.'-RefersTo'} || ''); + + foreach my $arg (keys %ARGS) { + next if $name_prefix && substr($arg, 0, length($name_prefix)) ne $name_prefix; + + my $article = RT::Article->new($session{'CurrentUser'}); + $article->LoadByInclude( + Field => substr($arg, length($name_prefix)), + Value => $ARGS{$arg}, + ); + if ($article->Id) { + $uri{$article->URI}++; + } + } +} + +use RT::Articles; + +my $articles_content = + RT::Articles->new( $session{'CurrentUser'} ); +my $articles_basics = RT::Articles->new( $session{'CurrentUser'} ); +if ( my $tmp = $ARGS{ $name_prefix ."Articles_Content" } ) { + $articles_content->LimitCustomField( + VALUE => $tmp, OPERATOR => 'LIKE' + ); + $articles_content->LimitAppliedClasses( Queue => $QueueObj ); + + $articles_basics->Limit( SUBCLAUSE => 'all', + FIELD => 'Name', + OPERATOR => 'LIKE', + VALUE => $tmp, + ENTRYAGGREGATOR => "OR" ); + $articles_basics->Limit( SUBCLAUSE => 'all', + FIELD => 'Summary', + OPERATOR => 'LIKE', + VALUE => $tmp, + ENTRYAGGREGATOR => "OR" ); + $articles_basics->LimitAppliedClasses( Queue => $QueueObj ); +} + +my $hotlist = RT::Articles->new( $session{'CurrentUser'} ); +$hotlist->LimitHotlistClasses; +$hotlist->LimitAppliedClasses( Queue => $QueueObj ); + +my ( $topic_articles, $topics, $included_topic ); +$topic_articles = RT::Articles->new( $session{CurrentUser} ); +$topics = []; + +my $top_topic = RT::Topic->new( $session{CurrentUser} ); +$top_topic->LoadByCols( Name => 'Queues', Parent => 0 , ObjectType => 'RT::System', ObjectId => 1); + +if ( $top_topic->id ) { + my $queue_topic = RT::Topic->new( $session{CurrentUser} ); + $queue_topic->LoadByCols( Name => $QueueObj->Name, Parent => $top_topic->id ); + if ( $queue_topic->id ) { + + # store all topics below $queue_topic to $topics + topics( $queue_topic, $topics, 0 ); + + if ( my $tmp = $ARGS{ $name_prefix .'Articles-Include-Topic'} ) { + $included_topic = RT::Topic->new( $session{CurrentUser} ); + $included_topic->Load( $tmp ); + $topic_articles->LimitTopics( $tmp ); + $topic_articles->OrderBy( FIELD => 'Name' ); + } + } +} + + +# recursively get all the topics given a top topic +sub topics { + my $parent = shift; + my $out = shift; + my $depth = shift; + while ( my $topic = $parent->Children->Next ) { + push @$out, { id => $topic->id, name => $topic->Name, depth => $depth }; + topics( $topic, $out, $depth+1 ); + } +} + + + + diff --git a/rt/share/html/Articles/Elements/CheckSkipCreate b/rt/share/html/Articles/Elements/CheckSkipCreate new file mode 100644 index 000000000..6524f2615 --- /dev/null +++ b/rt/share/html/Articles/Elements/CheckSkipCreate @@ -0,0 +1,76 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} +<%INIT> + +return if $checks_failure; # we're already skipping Create +return unless RT->Config->Get('ArticleOnTicketCreate'); + + +my $article = RT::Article->new($session{'CurrentUser'}); +foreach my $arg ( keys %$ARGSRef) { + + if ( $ARGSRef->{Articles_Content} || # search for an article + $ARGSRef->{'Articles-Include-Topic'} || # using Queue Topics + ( $article->LoadByInclude( Field => $arg, Value => $ARGSRef->{$arg} ) && + $article->id ) ) { # including an article + + $$skip_create = 1; + last; + } +} +return; + + + +<%ARGS> +$ARGSRef => undef +$skip_create => undef +$checks_failure => undef +$results => undef + + diff --git a/rt/share/html/Articles/Elements/CreateArticle b/rt/share/html/Articles/Elements/CreateArticle new file mode 100644 index 000000000..effd50315 --- /dev/null +++ b/rt/share/html/Articles/Elements/CreateArticle @@ -0,0 +1,59 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} +<& /Elements/TitleBoxStart, title => loc('Create an article') &> + +<& /Elements/TitleBoxEnd &> +<%init> +my $Classes = RT::Classes->new($session{'CurrentUser'}); +$Classes->LimitToEnabled; + + diff --git a/rt/share/html/Articles/Elements/GotoArticle b/rt/share/html/Articles/Elements/GotoArticle new file mode 100644 index 000000000..c8e5e5847 --- /dev/null +++ b/rt/share/html/Articles/Elements/GotoArticle @@ -0,0 +1,73 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} +
+ + +% if ($class or $topic) { + + +% } +  +
+<%args> +$topic => "" +$class => "" + diff --git a/rt/share/html/Articles/Elements/IncludeArticle b/rt/share/html/Articles/Elements/IncludeArticle new file mode 100644 index 000000000..f19815f58 --- /dev/null +++ b/rt/share/html/Articles/Elements/IncludeArticle @@ -0,0 +1,99 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} +<%INIT> + +my $parent_args = $m->caller_args(-1); + +my $name_prefix = ''; +$name_prefix = $ARGS{'Name'} .'-' + if $ARGS{'Name'} + && grep rindex($_, "$ARGS{'Name'}-Articles-", 0) == 0, + keys %$parent_args; + +foreach my $arg ( keys %$parent_args ) { + next if $name_prefix && substr($arg, 0, length($name_prefix)) ne $name_prefix; + + my $Ticket = $ARGS{Ticket}; + if ( !$Ticket and $parent_args->{id} and $parent_args->{id} ne 'new' ) { + $Ticket = RT::Ticket->new($session{'CurrentUser'}); + $Ticket->Load($parent_args->{id}); + unless ( $Ticket->id ) { + $RT::Logger->error("Couldn't load ticket ". $parent_args->{id} ) + } + } + + my $Queue = RT::Queue->new($session{CurrentUser}); + if ($Ticket && $Ticket->Id) { + $Queue = $Ticket->QueueObj; + } + + my $article = RT::Article->new($session{'CurrentUser'}); + $article->LoadByInclude( + Field => substr($arg, length($name_prefix)), + Value => $parent_args->{$arg}, + Queue => $Queue->Id, + ); + next unless $article && $article->id; + + my $formatted_article = $m->scomp('/Articles/Article/Elements/Preformatted', + Article => $article, Ticket => $Ticket + ); + + $m->callback( Article => $article, Ticket => $Ticket, formatted_article => \$formatted_article ); + + if (RT->Config->Get('MessageBoxRichText', $session{'CurrentUser'})) { + $formatted_article =~ s/>/>/g; + $formatted_article =~ s//g; + } + $m->print($formatted_article); + +} +return; + diff --git a/rt/share/html/Articles/Elements/NewestArticles b/rt/share/html/Articles/Elements/NewestArticles new file mode 100644 index 000000000..444b2d89d --- /dev/null +++ b/rt/share/html/Articles/Elements/NewestArticles @@ -0,0 +1,80 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} +<& /Elements/TitleBoxStart, title => loc("[_1] newest articles", $rows), bodyclass=> '' &> + + + + + + + +% while (my $Article = $MyArticles->Next) { +% $i++; + + + + + + + + + + +% } +
<&|/l&>#<&|/l&>Name<&|/l&>Created by 
<%$Article->Id%><%$Article->Name || loc('(no name)')%><%$Article->CreatorObj->Name%>[<&|/l&>Update]
 <%$Article->Summary || loc('(no Summary)')%>
+<& /Elements/TitleBoxEnd &> +<%INIT> +my $rows = 10; +my $i; +my $MyArticles; +$MyArticles = RT::Articles->new($session{'CurrentUser'}); +$MyArticles->UnLimit; +$MyArticles->RowsPerPage($rows); +$MyArticles->OrderBy(FIELD => 'LastUpdated', ORDER => 'DESC'); + + diff --git a/rt/share/html/Articles/Elements/QuickSearch b/rt/share/html/Articles/Elements/QuickSearch new file mode 100644 index 000000000..f0c0d1c89 --- /dev/null +++ b/rt/share/html/Articles/Elements/QuickSearch @@ -0,0 +1,59 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} +<& /Elements/TitleBoxStart, title => loc('Quick search') &> + +<& /Elements/TitleBoxEnd &> +<%init> +my $classes = RT::Classes->new($session{'CurrentUser'}); +$classes->LimitToEnabled; + + diff --git a/rt/share/html/Articles/Elements/SelectClass b/rt/share/html/Articles/Elements/SelectClass new file mode 100644 index 000000000..0ce90609e --- /dev/null +++ b/rt/share/html/Articles/Elements/SelectClass @@ -0,0 +1,95 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} +% if ($Lite) { + +% } else { + +% } +<%ARGS> +$Multiple => undef +$Size => undef +$ShowNullOption => 1 +$ShowAllClasses => 1 +$Name => undef +$Verbose => undef +$Default => undef +$Lite => 0 + + +<%INIT> + +my @Default = ref($Default) eq 'ARRAY' ? @$Default : ( $Default); + +my $Classes= RT::Classes->new($session{'CurrentUser'}); +$Classes->LimitToEnabled(); + +my $d = RT::Class->new($session{'CurrentUser'}); +$d->Load($Default[0]); + + diff --git a/rt/share/html/Articles/Elements/ShowTopic b/rt/share/html/Articles/Elements/ShowTopic new file mode 100644 index 000000000..da7c5f213 --- /dev/null +++ b/rt/share/html/Articles/Elements/ShowTopic @@ -0,0 +1,64 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} +% for (@path) { +%# this isn't always a class, it can be the system object +% my $class_id = ($_->ObjectType eq 'RT::Class' ? $_->ObjectId : 0 ); +<% $_->ParentObj->Id ? " > " : "" %><% $_->Name || loc("(no name)") %> +% } + +<%args> +$topic + + +<%init> +my @path; +while ($topic->Id) { + unshift @path, $topic; + $topic = $topic->ParentObj; +} + diff --git a/rt/share/html/Articles/Elements/UpdatedArticles b/rt/share/html/Articles/Elements/UpdatedArticles new file mode 100644 index 000000000..f2c5226be --- /dev/null +++ b/rt/share/html/Articles/Elements/UpdatedArticles @@ -0,0 +1,81 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} +<& /Elements/TitleBoxStart, title => loc("[_1] most recently updated articles", $rows), bodyclass=> '' &> + + + + + + + + +% while (my $Article = $MyArticles->Next) { +% $i++; + + + + + + + + + + +% } +
<&|/l&>#<&|/l&>Name<&|/l&>Created by 
<%$Article->Id%><%$Article->Name || loc('(no name)')%><%$Article->CreatorObj->Name%>[<&|/l&>Update]
 <%$Article->Summary || loc('(no Summary)')%>
+<& /Elements/TitleBoxEnd &> +<%INIT> +my $rows = 10; +my $i; +my $MyArticles; +$MyArticles = RT::Articles->new($session{'CurrentUser'}); +$MyArticles->RowsPerPage($rows); +$MyArticles->Limit(FIELD => 'Created', OPERATOR => '!=', VALUE => 'LastUpdated', QUOTEVALUE => 0 ); +$MyArticles->OrderBy(FIELD => 'Created', ORDER => 'DESC'); + + diff --git a/rt/share/html/Articles/Topics.html b/rt/share/html/Articles/Topics.html new file mode 100644 index 000000000..9a07c089a --- /dev/null +++ b/rt/share/html/Articles/Topics.html @@ -0,0 +1,276 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} +<& /Elements/Header, Title => loc('Browse by topic') &> +<& /Elements/Tabs &> + +<& /Elements/ListActions, actions => \@Actions &> +<&|/l&>All topics +% if (defined $class) { +> <% $currclass_name %> +% } + +% if ($id != 0) { +> <& /Articles/Elements/ShowTopic, topic => $currtopic &> +% } +
+

<&|/l&>Browse by topic

+<%perl> +if (defined $class) { + $m->print('

'.''.$currclass_name."

\n"); + ProduceTree(\@Actions, $currclass, $currclass_id, $currclass_name, 0, $id); +} else { + $m->print("\n"); +} + + +
+<%perl> +my @articles; +if ($id or $showall) { + my $Articles = RT::ObjectTopics->new($session{'CurrentUser'}); + $Articles->Limit(FIELD => 'ObjectType', VALUE => 'RT::Article'); + if ($id) { + $Articles->Limit(FIELD => 'Topic', VALUE => $id, ENTRYAGGREGATOR => 'OR'); + if ($showall) { + my $kids = $currtopic->Children; + while (my $k = $kids->Next) { + $Articles->Limit(FIELD => 'Topic', VALUE => $k->Id, + ENTRYAGGREGATOR => 'OR'); + } + } + } + @articles = map {$a = RT::Article->new($session{'CurrentUser'}); $a->Load($_->ObjectId); $a} @{$Articles->ItemsArrayRef} +} elsif ($class) { + my $Articles = RT::Articles->new($session{'CurrentUser'}); + my $TopicsAlias = $Articles->Join( + TYPE => 'left', + ALIAS1 => 'main', + FIELD1 => 'id', + TABLE2 => 'ObjectTopics', + FIELD2 => 'ObjectId', + ); + $Articles->Limit( + LEFTJOIN => $TopicsAlias, + FIELD => 'ObjectType', + VALUE => 'RT::Article', + ); + $Articles->Limit( + ALIAS => $TopicsAlias, + FIELD => 'Topic', + OPERATOR => 'IS', + VALUE => 'NULL', + QUOTEVALUE => 0, + ); + $Articles->Limit( + FIELD => 'Class', + OPERATOR => '=', + VALUE => $class, + ); + @articles = @{$Articles->ItemsArrayRef}; +} + + +% if (@articles) { +% if ($id) { +

<&|/l, $currtopic->Name&>Articles in [_1]

+% } elsif ($class) { +

<&|/l&>Articles with no topics

+% } + +% } + +<%init> +my @Actions; +my $Classes; +my $currclass; +my $currclass_id; +my $currclass_name; +my $currtopic; + +if ( defined $class ) { + if ($class) { + $currclass = RT::Class->new( $session{'CurrentUser'} ); + $currclass->Load($class); + $currclass_id = $currclass->Id; + $currclass_name = $currclass->Name; + } else { + $currclass = $RT::System; + $currclass_id = 0; + $currclass_name = 'Global Topics'; + } +} else { + $Classes = RT::Classes->new( $session{'CurrentUser'} ); + $Classes->LimitToEnabled(); +} + +if ($id) { + $currtopic = RT::Topic->new( $session{'CurrentUser'} ); + $currtopic->Load($id); +} + +# A subroutine that iterates through topics and their children, producing +# the necessary ul, li, and href links for the table of contents. Thank +# heaven for query caching. The $restrict variable is used to display only +# the branch of the hierarchy which contains that topic ID. + +sub ProduceTree { + my ( $Actions, $currclass, $currclass_id, $currclass_name, $parentid, $restrictid ) = @_; + $parentid = 0 unless $parentid; + + # Deal with tree restriction, if any. + if ($restrictid) { + my $rtopic = RT::Topic->new( $session{'CurrentUser'} ); + $rtopic->Load($restrictid); + unless ( $rtopic->Id() + && $rtopic->ObjectId() == $currclass_id ) + { + push( @{$Actions},"Could not restrict view to topic $restrictid"); + + # Start over, without the restriction. + &ProduceTree( $Actions, $currclass, $currclass_id, $currclass_name, $parentid, undef ); + } else { + my @showtopics; + push( @showtopics, $rtopic ); + my $parent = $rtopic->ParentObj; + while ( $parent->Id ) { + push( @showtopics, $parent ); + my $newparent = $parent->ParentObj; + $parent = $newparent; + } + + # List the topics. + my $indents = @showtopics; + while ( my $t = pop @showtopics ) { + print "
    "; + print &MakeLinks( $t, $currclass, $currclass_id, $currclass_name, $t->Children->Count ); + if ( $t->Id == $restrictid ) { + &ProduceTree( $Actions, $currclass, $currclass_id, $currclass_name, $restrictid, undef ); + } + } + print "
" x $indents; + } + } else { + + # No restriction in place. Build the entire tree. + my $topics = RT::Topics->new( $session{'CurrentUser'} ); + $topics->LimitToObject($currclass); + $topics->LimitToKids($parentid); + $topics->OrderBy( FIELD => 'Name' ); + print "
    " if $topics->Count; + while ( my $t = $topics->Next ) { + if ( $t->Children->Count ) { + print &MakeLinks( $t, $currclass, $currclass_id, $currclass_name, 1 ); + &ProduceTree( $Actions, $currclass, $currclass_id, $currclass_name, $t->Id ); + } else { + print &MakeLinks( $t, $currclass, $currclass_id, $currclass_name, 0 ); + } + } + print "
\n" if $topics->Count; + } +} + +sub MakeLinks { + my ( $topic, $currclass, $currclass_id, $currclass_name, $haschild ) = @_; + my $query; + my $output; + + if ( ref($topic) eq 'RT::Topic' ) { + + my $topic_info = $topic->Name() || loc("(no name)"); + $topic_info .= ": " . $topic->Description() if $topic->Description; + + if ($haschild) { # has topics below it + $query = "Topics.html?id=" . $topic->Id . "&class=" . $currclass_id; + $output = qq(
  • $topic_info); + } else { + $output = qq(
  • $topic_info); + } + + my $Articles = RT::ObjectTopics->new( $session{'CurrentUser'} ); + $Articles->Limit( FIELD => 'ObjectType', VALUE => 'RT::Article' ); + $Articles->Limit( FIELD => 'Topic', VALUE => $topic->Id ); + if ( $Articles->Count ) { + my $article_text = " (" . loc( "[quant,_1,article]", $Articles->Count ) . ")"; + my $query = "Topics.html?id=" . $topic->Id . "&class=$currclass_id&showall=1"; + $output .= qq($article_text); + } + + $output .= "
  • \n"; + + } else { + + # This builds a link for the class specified, with no particular topic. + $query = "Topics.html?class=" . $currclass_id; + $output = "
  • " . $currclass_name . ""; + $output .= ": " . $currclass->Description if $currclass->Description; + } + + return $output; +} + + + +<%args> +$id => 0 +$class => undef +$showall => undef + diff --git a/rt/share/html/Articles/index.html b/rt/share/html/Articles/index.html new file mode 100644 index 000000000..c4a1eab4e --- /dev/null +++ b/rt/share/html/Articles/index.html @@ -0,0 +1,63 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} +<& /Elements/Header, Title => loc('Articles') &> +<& /Elements/Tabs &> + + + + + +
    +<& /Articles/Elements/NewestArticles &> +
    +<& /Articles/Elements/UpdatedArticles &> +
    +<& /Articles/Elements/QuickSearch &> +
    +<& /Articles/Elements/CreateArticle &> +
    diff --git a/rt/share/html/Elements/EditCustomFieldDateTime b/rt/share/html/Elements/EditCustomFieldDateTime new file mode 100644 index 000000000..a558884b0 --- /dev/null +++ b/rt/share/html/Elements/EditCustomFieldDateTime @@ -0,0 +1,62 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} +% my $name = $NamePrefix.$CustomField->Id.'-Values'; +<& /Elements/SelectDate, Name => "$name", current => 0 &> (<%$DateObj->AsString%>) + +<%INIT> +my $DateObj = RT::Date->new ( $session{'CurrentUser'} ); +$DateObj->Set( Format => 'ISO', Value => $Default ); + +<%ARGS> +$Object => undef +$CustomField => undef +$NamePrefix => undef +$Default => undef +$Values => undef +$MaxValues => 1 + diff --git a/rt/share/html/Elements/EditCustomFieldIPAddress b/rt/share/html/Elements/EditCustomFieldIPAddress new file mode 100644 index 000000000..ae57fce87 --- /dev/null +++ b/rt/share/html/Elements/EditCustomFieldIPAddress @@ -0,0 +1,50 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} +<%INIT> +return $m->comp( 'EditCustomFieldFreeform', %ARGS ); + diff --git a/rt/share/html/Elements/EditCustomFieldIPAddressRange b/rt/share/html/Elements/EditCustomFieldIPAddressRange new file mode 100644 index 000000000..ae57fce87 --- /dev/null +++ b/rt/share/html/Elements/EditCustomFieldIPAddressRange @@ -0,0 +1,50 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} +<%INIT> +return $m->comp( 'EditCustomFieldFreeform', %ARGS ); + diff --git a/rt/share/html/Elements/Framekiller b/rt/share/html/Elements/Framekiller new file mode 100644 index 000000000..3b54da192 --- /dev/null +++ b/rt/share/html/Elements/Framekiller @@ -0,0 +1,67 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} +% if ( RT->Config->Get('Framebusting') ) { +%# This is defeatable. The current best known implemention uses CSS to hide +%# the content and JS to re-show it, but that fails poorly for clients that +%# don't run JS. + +% } diff --git a/rt/share/html/Elements/QueriesAsComment b/rt/share/html/Elements/QueriesAsComment new file mode 100644 index 000000000..2658cc444 --- /dev/null +++ b/rt/share/html/Elements/QueriesAsComment @@ -0,0 +1,58 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} +<%INIT> +return unless RT->Config->Get('StatementLog') + && $session{'CurrentUser'}->HasRight( Object=> $RT::System, Right => 'SuperUser'); + + diff --git a/rt/share/html/Elements/QueueSummaryByLifecycle b/rt/share/html/Elements/QueueSummaryByLifecycle new file mode 100644 index 000000000..1410e82ef --- /dev/null +++ b/rt/share/html/Elements/QueueSummaryByLifecycle @@ -0,0 +1,145 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} +<%perl> + foreach my $lifecycle ( map $lifecycle{$_}, sort keys %lifecycle ) { + my @cur_statuses = grep $lifecycle->IsValid($_), @statuses; + next unless @cur_statuses; + + + + + + +% for my $status ( @cur_statuses ) { + +% } + + +<%PERL> +my $i = 0; +for my $queue (@queues) { + next if lc($queue->{Lifecycle} || '') ne lc $lifecycle->Name; + + $i++; + my $name = $queue->{Name}; + $name =~ s/(['\\])/\\$1/g; + my $queue_cond = "Queue = '$name' AND "; + my $all_q = $queue_cond . '(' . join( " OR ", map "Status = '$_'", @cur_statuses ) . ')'; + + + + + +% for my $status (@cur_statuses) { + +% } + +% } +
    <&|/l&>Queue<% loc($status) %>
    + <% $queue->{Name} %> + + "><% $data->{$queue->{id}}->{$status } || '-' %> +
    +% } +<%INIT> + +my $Queues = RT::Queues->new( $session{'CurrentUser'} ); +$Queues->UnLimit(); +$m->callback( CallbackName => 'SQLFilter', Queues => $Queues ); + +my @queues = grep $queue_filter->($_), @{ $Queues->ItemsArrayRef }; +$m->callback( CallbackName => 'Filter', Queues => \@queues ); + +@queues = map { + { id => $_->Id, + Name => $_->Name, + Description => $_->Description || '', + Lifecycle => $_->Lifecycle->Name, + } +} grep $_, @queues; + +my %lifecycle; + +for my $queue (@queues) { + my $cycle = RT::Lifecycle->Load( $queue->{'Lifecycle'} ); + $lifecycle{ lc $cycle->Name } = $cycle; +} + +unless (@statuses) { + my %seen; + foreach my $set ( 'initial', 'active' ) { + foreach my $lifecycle ( map $lifecycle{$_}, sort keys %lifecycle ) { + push @statuses, grep !$seen{ lc $_ }++, $lifecycle->Valid($set); + } + } +} + +my $data = {}; +my $statuses = {}; + +use RT::Report::Tickets; +my $report = RT::Report::Tickets->new( RT->SystemUser ); +my $query = + "(". + join(" OR ", map {s{(['\\])}{\\$1}g; "Status = '$_'"} @statuses) #' + .") AND (". + join(' OR ', map "Queue = ".$_->{id}, @queues) + .")"; +$query = 'id < 0' unless @queues; +$report->SetupGroupings( Query => $query, GroupBy => [qw(Status Queue)] ); + +while ( my $entry = $report->Next ) { + $data->{ $entry->__Value("Queue") }->{ $entry->__Value("Status") } + = $entry->__Value('id'); + $statuses->{ $entry->__Value("Status") } = 1; +} + +<%ARGS> +$queue_filter => undef +@statuses => () + diff --git a/rt/share/html/Elements/QueueSummaryByStatus b/rt/share/html/Elements/QueueSummaryByStatus new file mode 100644 index 000000000..09f274f74 --- /dev/null +++ b/rt/share/html/Elements/QueueSummaryByStatus @@ -0,0 +1,139 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} + + + + +% for my $status ( @statuses ) { + +% } + + +<%PERL> +my $i = 0; +for my $queue (@queues) { + $i++; + my $name = $queue->{Name}; + $name =~ s/(['\\])/\\$1/g; + my $queue_cond = "Queue = '$name' AND "; + my $lifecycle = $lifecycle{ lc $queue->{'Lifecycle'} }; + my $all_q = $queue_cond . '(' . join( " OR ", map "Status = '$_'", grep $lifecycle->IsValid($_), @statuses ) . ')'; + + + + + +<%perl> + for my $status (@statuses) { + if ( $lifecycle->IsValid( $status ) ) { + + +% } else { + +% } +% } + +% } +
    <&|/l&>Queue<% loc($status) %>
    + <% $queue->{Name} %> + + "><% $data->{$queue->{id}}->{$status } || '-' %> +-
    +<%INIT> + +my $Queues = RT::Queues->new( $session{'CurrentUser'} ); +$Queues->UnLimit(); +$m->callback( CallbackName => 'SQLFilter', Queues => $Queues ); + +my @queues = grep $queue_filter->($_), @{ $Queues->ItemsArrayRef }; +$m->callback( CallbackName => 'Filter', Queues => \@queues ); + +@queues = map { + { id => $_->Id, + Name => $_->Name, + Description => $_->Description || '', + Lifecycle => $_->Lifecycle->Name, + } +} grep $_, @queues; + +my %lifecycle; + +for my $queue (@queues) { + my $cycle = RT::Lifecycle->Load( $queue->{'Lifecycle'} ); + $lifecycle{ lc $cycle->Name } = $cycle; +} + +unless (@statuses) { + my %seen; + foreach my $set ( 'initial', 'active' ) { + foreach my $lifecycle ( map $lifecycle{$_}, sort keys %lifecycle ) { + push @statuses, grep !$seen{ lc $_ }++, $lifecycle->Valid($set); + } + } +} + +my $data = {}; +my $statuses = {}; + +use RT::Report::Tickets; +my $report = RT::Report::Tickets->new( RT->SystemUser ); +my $query = @queues + ? join(' OR ', map "Queue = ".$_->{id}, @queues) + : 'id < 0'; +$report->SetupGroupings( Query => $query, GroupBy => [qw(Status Queue)] ); + +while ( my $entry = $report->Next ) { + $data->{ $entry->__Value("Queue") }->{ $entry->__Value("Status") } + = $entry->__Value('id'); + $statuses->{ $entry->__Value("Status") } = 1; +} + +<%ARGS> +$queue_filter => undef +@statuses => () + diff --git a/rt/share/html/Elements/RT__Article/ColumnMap b/rt/share/html/Elements/RT__Article/ColumnMap new file mode 100644 index 000000000..133f3d463 --- /dev/null +++ b/rt/share/html/Elements/RT__Article/ColumnMap @@ -0,0 +1,107 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} +<%ARGS> +$Name => undef +$Attr => undef + + + +<%ONCE> +my $COLUMN_MAP; + +$COLUMN_MAP = { + Name => { + attribute => 'Name', + title => 'Name', # loc + value => sub { $_[0]->Name }, + }, + Summary => { + attribute => 'Summary', + title => 'Summary', # loc + value => sub { $_[0]->Summary }, + }, + Class => { + attribute => 'Class', + title => 'Class id', # loc + value => sub { $_[0]->Class }, + }, + ClassName => { + attribute => 'Class', + title => 'Class', # loc + value => sub { $_[0]->ClassObj->Name }, + }, + CreatedRelative => { + attribute => 'Created', + title => 'Created', # loc + value => sub { $_[0]->CreatedObj->AgeAsString }, + }, + LastUpdatedRelative => { + attribute => 'LastUpdated', + title => 'LastUpdated', # loc + value => sub { $_[0]->LastUpdatedObj->AgeAsString }, + }, + Topics => { + title => 'Topics', # loc + value => sub { + my $topics = ''; + my $Topics = $_[0]->Topics; + while ( my $t = $Topics->Next ) { + $topics .= + $m->scomp( '/Articles/Elements/ShowTopic', topic => $t->TopicObj ) + . '
    '; + } + return \$topics; + }, + } +}; + + +<%init> +$m->callback( COLUMN_MAP => $COLUMN_MAP, CallbackName => 'Once', CallbackOnce => 1 ); +return GetColumnMapEntry( Map => $COLUMN_MAP, Name => $Name, Attribute => $Attr ); + diff --git a/rt/share/html/Elements/RT__Class/ColumnMap b/rt/share/html/Elements/RT__Class/ColumnMap new file mode 100644 index 000000000..3875d96e8 --- /dev/null +++ b/rt/share/html/Elements/RT__Class/ColumnMap @@ -0,0 +1,76 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} +<%ARGS> +$Name +$Attr => undef + +<%ONCE> +my $COLUMN_MAP = { + id => { + title => '#', # loc + attribute => 'id', + value => sub { return $_[0]->id }, + }, + Name => { + title => 'Name', # loc + attribute => 'Name', + value => sub { return $_[0]->Name() }, + }, + Description => { + title => 'Description', # loc + attribute => 'Description', + value => sub { return $_[0]->Description() }, + }, +}; + + + +<%INIT> +$m->callback( COLUMN_MAP => $COLUMN_MAP, CallbackName => 'ColumnMap', CallbackOnce => 1 ); +return GetColumnMapEntry( Map => $COLUMN_MAP, Name => $Name, Attribute => $Attr ); + diff --git a/rt/share/html/Elements/RT__Dashboard/ColumnMap b/rt/share/html/Elements/RT__Dashboard/ColumnMap new file mode 100644 index 000000000..8bc4383d8 --- /dev/null +++ b/rt/share/html/Elements/RT__Dashboard/ColumnMap @@ -0,0 +1,134 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} +<%ARGS> +$Name +$Attr => undef + +<%ONCE> +my $COLUMN_MAP = { + id => { + title => '#', # loc + attribute => 'id', + align => 'right', + value => sub { return $_[0]->Id }, + }, + Name => { + title => 'Name', # loc + attribute => 'Name', + value => sub { return $_[0]->Name()||loc("Unnamed dashboard") }, + }, + Subscription => { + title => 'Subscription', # loc + attribute => 'Subscription', + value => sub { + my $Dashboard = shift; + my $Subscription = $Dashboard->Subscription; + + my $url = sprintf '%s/Dashboards/Subscription.html?id=%d', + RT->Config->Get('WebPath'), + $Dashboard->Id; + + my $frequency = loc("None"); + + if (defined $Subscription) { + my $freq = $Subscription->SubValue('Frequency'); + my $hour = $Subscription->SubValue('Hour'); + + if (my ($integer_hour) = $hour =~ /^(\d\d):00$/) { + my $formatter = RT::Date->new($session{CurrentUser})->LocaleObj; + my $dt = DateTime->now; + $dt->set_minute(0); + $dt->set_second(0); + $dt->set_hour($integer_hour); + + # use the formatted hour instead + $hour = $dt->format_cldr($formatter->time_format_short); + } + + if ($freq eq 'weekly') { + my $day = $Subscription->SubValue('Dow'); + $frequency = loc("weekly (on [_1]) at [_2]", loc($day), $hour); + } + elsif ($freq eq 'monthly') { + $frequency = loc("monthly (day [_1]) at [_2]", $Subscription->SubValue('Dom'), $hour); + } + elsif ($freq eq 'daily') { + $frequency = loc("daily at [_1]", $hour); + } + elsif ($freq eq 'm-f') { + $frequency = loc("M-F at [_1]", $hour); + } + elsif ($freq eq 'never') { + $frequency = loc("Never"); + } + else { + $frequency = loc($freq); + } + } + + return \(''.$frequency.''); + }, + }, + ShowURL => { + title => '', + attribute => 'ShowURL', + value => sub { + my $dashboard = shift; + my $id = $dashboard->Id; + my $name = $dashboard->Name; + + return "Dashboards/$id/$name"; + }, + } +}; + + +<%INIT> +$m->callback( COLUMN_MAP => $COLUMN_MAP, CallbackName => 'ColumnMap', CallbackOnce => 1 ); +return GetColumnMapEntry( Map => $COLUMN_MAP, Name => $Name, Attribute => $Attr ); + diff --git a/rt/share/html/Elements/SelectIPRelation b/rt/share/html/Elements/SelectIPRelation new file mode 100644 index 000000000..ec9f58d13 --- /dev/null +++ b/rt/share/html/Elements/SelectIPRelation @@ -0,0 +1,64 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} + + +<%ARGS> +$Name => undef +@Options => ( loc('is'), loc("isn't"), loc('less than'), loc('greater than')) +@Values => ('=', '!=', '<', '>') +$Default => '' + diff --git a/rt/share/html/Elements/SelectOwnerAutocomplete b/rt/share/html/Elements/SelectOwnerAutocomplete new file mode 100644 index 000000000..cf2010a80 --- /dev/null +++ b/rt/share/html/Elements/SelectOwnerAutocomplete @@ -0,0 +1,102 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} +<%ARGS> +$Name => undef +$Objects => [] +$Default => 0 +$ValueAttribute => 'Name' +$TicketObj => undef + +<%INIT> +$ValueAttribute = 'Name' unless $ValueAttribute =~ /^(?:id|Name)$/; + +my $value = ''; + +if ( $Default and not $Default =~ /\D/ ) { + my $user = RT::User->new( $session{'CurrentUser'} ); + $user->Load($Default); + $value = $user->$ValueAttribute; +} elsif (defined $TicketObj) { + $value = $TicketObj->OwnerObj->$ValueAttribute; +} + +# Map to a string of RT::Ticket-1|RT::Queue-5|... +my $limit = join '|', map { join '-', ref($_), ($_->id || '') } @$Objects; + +my $query = $m->comp('/Elements/QueryString', + return => $ValueAttribute, + limit => $limit, +); + + + + + diff --git a/rt/share/html/Elements/SelectOwnerDropdown b/rt/share/html/Elements/SelectOwnerDropdown new file mode 100644 index 000000000..5dd642960 --- /dev/null +++ b/rt/share/html/Elements/SelectOwnerDropdown @@ -0,0 +1,99 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} + +<%INIT> +my %user_uniq_hash; + +my $isSU = $session{CurrentUser} + ->HasRight( Right => 'SuperUser', Object => $RT::System ); +foreach my $object (@$Objects) { + my $Users = RT::Users->new( $session{CurrentUser} ); + $Users->WhoHaveRight( + Right => 'OwnTicket', + Object => $object, + IncludeSystemRights => 1, + IncludeSuperusers => $isSU + ); + while ( my $User = $Users->Next() ) { + $user_uniq_hash{ $User->Id() } = $User; + } +} +if ($Default && $Default != RT->Nobody->id && !$user_uniq_hash{$Default}) { + $user_uniq_hash{$Default} = RT::User->new($session{CurrentUser}); + $user_uniq_hash{$Default}->Load($Default); +} + +my @users = values %user_uniq_hash; + + +<%ARGS> +$Name => undef +$Objects => [] +$Default => 0 +$DefaultValue => 1 +$DefaultLabel => "-" +$ValueAttribute => 'id' + diff --git a/rt/share/html/Elements/ShowCustomFieldDateTime b/rt/share/html/Elements/ShowCustomFieldDateTime new file mode 100644 index 000000000..e7a9a2bdc --- /dev/null +++ b/rt/share/html/Elements/ShowCustomFieldDateTime @@ -0,0 +1,57 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} +<%INIT> + my $content = $Object->Content; + my $DateObj = RT::Date->new ( $session{'CurrentUser'} ); + $DateObj->Set( Format => 'ISO', Value => $content ); + $content = $DateObj->AsString; + +<%$content|n%> +<%ARGS> +$Object + diff --git a/rt/share/html/Elements/ShowReminders b/rt/share/html/Elements/ShowReminders new file mode 100644 index 000000000..34cde464a --- /dev/null +++ b/rt/share/html/Elements/ShowReminders @@ -0,0 +1,101 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} +% if ( $reminders->Count ) { + + + + + + +<%PERL> +my $i =0; +while ( my $reminder = $reminders->Next ) { +$i++; +my $dueobj = $reminder->DueObj; +my $overdue = $dueobj->Unix > 0 && $dueobj->Diff < 0 ? 1 : 0; + +my $targets = RT::Tickets->new($session{'CurrentUser'}); +$targets->FromSQL( "ReferredToBy = " . $reminder->id ); + +if ( my $ticket= $targets->First ) { + + + + + +% } else { + +% } + +% } +
    <&|/l&>Reminder<&|/l&>Due<&|/l&>Ticket
    +<% $reminder->Subject %> + +<% $overdue ? '' : '' |n %><% $dueobj->AgeAsString || loc('Not set') %><% $overdue ? '' : '' |n %> + +#<% $ticket->Id %>: <% $ticket->Subject %> +
    Couldn't find Ticket for reminder <% $reminder->id %>. Please contact administrator.
    +
    +% } + +<%INIT> +my $reminders = RT::Tickets->new($session{'CurrentUser'}); +my $tsql = 'Type = "reminder"' . + ' AND ( Owner = "Nobody" OR Owner ="' . $session{'CurrentUser'}->id . '")' . + ' AND ( Status = "new" OR Status = "open" )'; + +$tsql .= ' AND Due < "now"' if $OnlyOverdue; + +$reminders->FromSQL($tsql); +$reminders->OrderBy( FIELD => 'Due', ORDER => 'ASC' ); + + +<%ARGS> +$OnlyOverdue => 0 + diff --git a/rt/share/html/Elements/WidgetBar b/rt/share/html/Elements/WidgetBar new file mode 100644 index 000000000..35e7fe215 --- /dev/null +++ b/rt/share/html/Elements/WidgetBar @@ -0,0 +1,58 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} +% return unless ($menu); +% for my $child ($menu->children) { +% if (defined $child->raw_html) { +<% $child->raw_html |n %> +% } else { +<% $child->title %>\ +% } +% } +<%ARGS> +$menu + diff --git a/rt/share/html/Helpers/Autocomplete/Groups b/rt/share/html/Helpers/Autocomplete/Groups new file mode 100644 index 000000000..e8baf5397 --- /dev/null +++ b/rt/share/html/Helpers/Autocomplete/Groups @@ -0,0 +1,88 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} +% $r->content_type('application/json'); +<% JSON( \@suggestions ) |n %> +% $m->abort; +<%ARGS> +$term => undef +$max => 10 +$exclude => '' +$op => 'LIKE' + +<%INIT> +$m->abort unless defined $term + and length $term; + +my $CurrentUser = $session{'CurrentUser'}; + +# Require privileged users +$m->abort unless $CurrentUser->Privileged; + +# Sanity check the operator +$op = 'LIKE' unless $op =~ /^(?:LIKE|(?:START|END)SWITH|=|!=)$/i; + +my $groups = RT::Groups->new( $CurrentUser ); +$groups->RowsPerPage( $max ); +$groups->LimitToUserDefinedGroups(); +$groups->Limit( + FIELD => 'Name', + OPERATOR => $op, + VALUE => $term, +); + +# Exclude groups we don't want +foreach (split /\s*,\s*/, $exclude) { + $groups->Limit(FIELD => 'id', VALUE => $_, OPERATOR => '!='); +} + +my @suggestions; + +while ( my $group = $groups->Next ) { + push @suggestions, $group->Name; +} + diff --git a/rt/share/html/Helpers/Autocomplete/Owners b/rt/share/html/Helpers/Autocomplete/Owners new file mode 100644 index 000000000..1d065f2a2 --- /dev/null +++ b/rt/share/html/Helpers/Autocomplete/Owners @@ -0,0 +1,150 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} +% $r->content_type('application/json'); +<% JSON( \@suggestions ) |n %> +% $m->abort; +<%ARGS> +$return => 'Name' +$limit => undef +$term => undef +$max => 10 + +<%INIT> +# Only allow certain return fields +$return = 'Name' + unless $return =~ /^(?:EmailAddress|Name|RealName|id)$/; + +$m->abort unless defined $return + and defined $term + and defined $limit; + +my $CurrentUser = $session{'CurrentUser'}; + +my %fields = %{ RT->Config->Get('UserAutocompleteFields') + || { EmailAddress => 1, Name => 1, RealName => 'LIKE' } }; + +my %user_uniq_hash; +my $isSU = $session{CurrentUser} + ->HasRight( Right => 'SuperUser', Object => $RT::System ); + +# Turn RT::Ticket-1|RT::Queue-2 into ['RT::Ticket', 1], ['RT::Queue', 2] +foreach my $spec (map { [split /\-/, $_, 2] } split /\|/, $limit) { + next unless $spec->[0] =~ /^RT::(Ticket|Queue)$/; + + my $object = $spec->[0]->new( $session{'CurrentUser'} ); + + if ( $spec->[1] ) { + $object->Load( $spec->[1] ); + + # Warn if we couldn't load an object + unless ( $object->id ) { + $RT::Logger->warn("Owner autocomplete couldn't load an '$spec->[0]' with id '$spec->[1]'"); + next; + } + } + + my $Users = RT::Users->new( $session{CurrentUser} ); + $Users->RowsPerPage( $max ); + + # Limit by our autocomplete term BEFORE we limit to OwnTicket because that + # does a funky union hack + while (my ($name, $op) = each %fields) { + $op = 'STARTSWITH' + unless $op =~ /^(?:LIKE|(?:START|END)SWITH)$/i; + + $Users->Limit( + FIELD => $name, + OPERATOR => $op, + VALUE => $term, + ENTRYAGGREGATOR => 'OR', + SUBCLAUSE => 'autocomplete', + ); + } + + $Users->WhoHaveRight( + Right => 'OwnTicket', + Object => $object, + IncludeSystemRights => 1, + IncludeSuperusers => $isSU + ); + + while ( my $User = $Users->Next() ) { + next if $user_uniq_hash{ $User->Id }; + $user_uniq_hash{ $User->Id() } = [ + $User, + $m->scomp('/Elements/ShowUser', User => $User, NoEscape => 1) + ]; + } +} + +# Make sure we add Nobody if we don't already have it +my $nobody = qr/^n(?:o(?:b(?:o(?:d(?:y)?)?)?)?)?$/i; +if ( not $user_uniq_hash{RT->Nobody->id} and $term =~ $nobody ) { + $user_uniq_hash{RT->Nobody->id} = [ + RT->Nobody, + $m->scomp('/Elements/ShowUser', User => RT->Nobody, NoEscape => 1) + ]; +} + +my @users = sort { lc $a->[1] cmp lc $b->[1] } + values %user_uniq_hash; + +my @suggestions; +my $count = 1; + +for my $tuple ( @users ) { + last if $count > $max; + my $formatted = $tuple->[1]; + $formatted =~ s/\n//g; + push @suggestions, { + label => $formatted, + value => $tuple->[0]->$return + }; + $count++; +} + diff --git a/rt/share/html/Helpers/Autocomplete/Users b/rt/share/html/Helpers/Autocomplete/Users new file mode 100644 index 000000000..dbc2d888f --- /dev/null +++ b/rt/share/html/Helpers/Autocomplete/Users @@ -0,0 +1,130 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} +% $r->content_type('application/json'); +<% JSON( \@suggestions ) |n %> +% $m->abort; +<%ARGS> +$return => '' +$term => undef +$delim => undef +$max => 10 +$privileged => undef +$exclude => '' +$op => undef + +<%INIT> +# Only allow certain return fields +$return = 'EmailAddress' + unless $return =~ /^(?:EmailAddress|Name|RealName)$/; + +$m->abort unless defined $return + and defined $term + and length $term; + +# Use our delimeter if we have one +if ( defined $delim and length $delim ) { + if ( $delim eq ',' ) { + $delim = qr/,\s*/; + } else { + $delim = qr/\Q$delim\E/; + } + + # If the field handles multiple values, pop the last one off + $term = (split $delim, $term)[-1] if $term =~ $delim; +} + +my $CurrentUser = $session{'CurrentUser'}; + +# Require privileged users or overriding config +$m->abort unless $CurrentUser->Privileged + or RT->Config->Get('AllowUserAutocompleteForUnprivileged'); + +my %fields = %{ RT->Config->Get('UserAutocompleteFields') + || { EmailAddress => 1, Name => 1, RealName => 'LIKE' } }; + +# If an operator is provided, check against only the returned field +# using that operator +%fields = ( $return => $op ) if $op; + +my $users = RT::Users->new( $CurrentUser ); +$users->RowsPerPage( $max ); + +$users->LimitToPrivileged() if $privileged; + +while (my ($name, $op) = each %fields) { + $op = 'STARTSWITH' + unless $op =~ /^(?:LIKE|(?:START|END)SWITH|=|!=)$/i; + + $users->Limit( + FIELD => $name, + OPERATOR => $op, + VALUE => $term, + ENTRYAGGREGATOR => 'OR', + SUBCLAUSE => 'autocomplete', + ); +} + +# Exclude users we don't want +foreach (split /\s*,\s*/, $exclude) { + $users->Limit(FIELD => 'id', VALUE => $_, OPERATOR => '!='); +} + +my @suggestions; + +while ( my $user = $users->Next ) { + next if $user->id == RT->SystemUser->id + or $user->id == RT->Nobody->id; + + my $formatted = $m->scomp('/Elements/ShowUser', User => $user, NoEscape => 1); + $formatted =~ s/\n//g; + my $suggestion = { label => $formatted, value => $user->$return }; + $m->callback( CallbackName => "ModifySuggestion", suggestion => $suggestion, user => $user ); + push @suggestions, $suggestion; +} + + diff --git a/rt/share/html/Helpers/TicketHistory b/rt/share/html/Helpers/TicketHistory new file mode 100644 index 000000000..357ee8f96 --- /dev/null +++ b/rt/share/html/Helpers/TicketHistory @@ -0,0 +1,67 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} +<%ARGS> +$id + +<%INIT> +my $TicketObj = RT::Ticket->new($session{'CurrentUser'}); +$TicketObj->Load($id); + +my $attachments = $m->comp('/Ticket/Elements/FindAttachments', Ticket => $TicketObj); +my $attachment_content = $m->comp('/Ticket/Elements/LoadTextAttachments', Ticket => $TicketObj); + +$m->comp('/Ticket/Elements/ShowHistory', + Ticket => $TicketObj, + Collapsed => $ARGS{'Collapsed'}, + ShowHeaders => $ARGS{'ShowHeaders'}, + Attachments => $attachments, + AttachmentContent => $attachment_content +); + +$m->abort(); + diff --git a/rt/share/html/Helpers/Toggle/ShowRequestor b/rt/share/html/Helpers/Toggle/ShowRequestor new file mode 100644 index 000000000..bb90b9887 --- /dev/null +++ b/rt/share/html/Helpers/Toggle/ShowRequestor @@ -0,0 +1,63 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} +<%INIT> +my $TicketTemplate = "/Ticket/Elements/ShowRequestorTickets$Status"; +$TicketTemplate = "/Ticket/Elements/ShowRequestorTicketsActive" unless $m->comp_exists($TicketTemplate); +my $user_obj = RT::User->new($session{CurrentUser}); +my ($val, $msg) = $user_obj->Load($Requestor); +unless ($val) { + $RT::Logger->error("Unable to load User $Requestor: $msg"); +} else { + $m->comp( $TicketTemplate, Requestor => $user_obj ); +} +$m->abort(); + +<%ARGS> +$Status +$Requestor + diff --git a/rt/share/html/NoAuth/Helpers/CustomLogo/dhandler b/rt/share/html/NoAuth/Helpers/CustomLogo/dhandler new file mode 100644 index 000000000..86e48e2e5 --- /dev/null +++ b/rt/share/html/NoAuth/Helpers/CustomLogo/dhandler @@ -0,0 +1,61 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} +<%INIT> +if ( my $attr = $RT::System->FirstAttribute('UserLogo') ) { + # The extra path in the url doesn't matter, we always want to serve the + # latest logo if we have one. + RT::Interface::Web::StaticFileHeaders(); + my $content = $attr->Content; + $r->content_type( $content->{type} ); + $m->out( $content->{data} ); +} +else { + # 404 + return $m->decline; +} + diff --git a/rt/share/html/NoAuth/RichText/ckeditor/LICENSE.html b/rt/share/html/NoAuth/RichText/ckeditor/LICENSE.html new file mode 100644 index 000000000..f7ba06793 --- /dev/null +++ b/rt/share/html/NoAuth/RichText/ckeditor/LICENSE.html @@ -0,0 +1,1334 @@ + + + + + License - CKEditor + + +

    + Software License Agreement +

    +

    + CKEditor™ - The text editor for Internet™ - + http://ckeditor.com
    + Copyright © 2003-2010, CKSource - Frederico Knabben. All rights reserved. +

    +

    + Licensed under the terms of any of the following licenses at your choice: +

    + +

    + You are not required to, but if you want to explicitly declare the license you have + chosen to be bound to when using, reproducing, modifying and distributing this software, + just include a text file titled "LEGAL" in your version of this software, indicating + your license choice. In any case, your choice will not restrict any recipient of + your version of this software to use, reproduce, modify and distribute this software + under any of the above licenses. +

    +

    + Sources of Intellectual Property Included in CKEditor +

    +

    + Where not otherwise indicated, all CKEditor content is authored by CKSource engineers + and consists of CKSource-owned intellectual property. In some specific instances, + CKEditor will incorporate work done by developers outside of CKSource with their + express permission. +

    +

    + YUI Test: At _source/tests/yuitest.js + can be found part of the source code of YUI, which is licensed under the terms of + the BSD License. YUI is + Copyright © 2008, Yahoo! Inc. +

    +

    + Trademarks +

    +

    + CKEditor is a trademark of CKSource - Frederico Knabben. All other brand and product + names are trademarks, registered trademarks or service marks of their respective + holders. +

    + + diff --git a/rt/share/html/NoAuth/RichText/ckeditor/adapters/jquery.js b/rt/share/html/NoAuth/RichText/ckeditor/adapters/jquery.js new file mode 100644 index 000000000..f60345978 --- /dev/null +++ b/rt/share/html/NoAuth/RichText/ckeditor/adapters/jquery.js @@ -0,0 +1,6 @@ +/* +Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.html or http://ckeditor.com/license +*/ + +(function(){CKEDITOR.config.jqueryOverrideVal=typeof CKEDITOR.config.jqueryOverrideVal=='undefined'?true:CKEDITOR.config.jqueryOverrideVal;var a=window.jQuery;if(typeof a=='undefined')return;a.extend(a.fn,{ckeditorGet:function(){var b=this.eq(0).data('ckeditorInstance');if(!b)throw 'CKEditor not yet initialized, use ckeditor() with callback.';return b;},ckeditor:function(b,c){if(!a.isFunction(b)){var d=c;c=b;b=d;}c=c||{};this.filter('textarea, div, p').each(function(){var e=a(this),f=e.data('ckeditorInstance'),g=e.data('_ckeditorInstanceLock'),h=this;if(f&&!g){if(b)b.apply(f,[this]);}else if(!g){if(c.autoUpdateElement||typeof c.autoUpdateElement=='undefined'&&CKEDITOR.config.autoUpdateElement)c.autoUpdateElementJquery=true;c.autoUpdateElement=false;e.data('_ckeditorInstanceLock',true);f=CKEDITOR.replace(h,c);e.data('ckeditorInstance',f);f.on('instanceReady',function(i){var j=i.editor;setTimeout(function(){if(!j.element){setTimeout(arguments.callee,100);return;}i.removeListener('instanceReady',this.callee);j.on('dataReady',function(){e.trigger('setData.ckeditor',[j]);});j.on('getData',function(l){e.trigger('getData.ckeditor',[j,l.data]);},999);j.on('destroy',function(){e.trigger('destroy.ckeditor',[j]);});if(j.config.autoUpdateElementJquery&&e.is('textarea')&&e.parents('form').length){var k=function(){e.ckeditor(function(){j.updateElement();});};e.parents('form').submit(k);e.parents('form').bind('form-pre-serialize',k);e.bind('destroy.ckeditor',function(){e.parents('form').unbind('submit',k);e.parents('form').unbind('form-pre-serialize',k);});}j.on('destroy',function(){e.data('ckeditorInstance',null);});e.data('_ckeditorInstanceLock',null);e.trigger('instanceReady.ckeditor',[j]);if(b)b.apply(j,[h]);},0);},null,null,9999);}else CKEDITOR.on('instanceReady',function(i){var j=i.editor;setTimeout(function(){if(!j.element){setTimeout(arguments.callee,100);return;}if(j.element.$==h)if(b)b.apply(j,[h]);},0);},null,null,9999);});return this;}});if(CKEDITOR.config.jqueryOverrideVal)a.fn.val=CKEDITOR.tools.override(a.fn.val,function(b){return function(c,d){var e=typeof c!='undefined',f;this.each(function(){var g=a(this),h=g.data('ckeditorInstance');if(!d&&g.is('textarea')&&h){if(e)h.setData(c);else{f=h.getData();return null;}}else if(e)b.call(g,c);else{f=b.call(g);return null;}return true;});return e?this:f;};});})(); diff --git a/rt/share/html/NoAuth/RichText/ckeditor/ckeditor.js b/rt/share/html/NoAuth/RichText/ckeditor/ckeditor.js new file mode 100644 index 000000000..77b165e03 --- /dev/null +++ b/rt/share/html/NoAuth/RichText/ckeditor/ckeditor.js @@ -0,0 +1,135 @@ +/* +Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.html or http://ckeditor.com/license +*/ + +(function(){if(!window.CKEDITOR)window.CKEDITOR=(function(){var a={timestamp:'A8LE4JO',version:'3.4.1',revision:'5892',_:{},status:'unloaded',basePath:(function(){var d=window.CKEDITOR_BASEPATH||'';if(!d){var e=document.getElementsByTagName('script');for(var f=0;f=0?'&':'?')+'t='+this.timestamp;return d;}},b=window.CKEDITOR_GETURL;if(b){var c=a.getUrl;a.getUrl=function(d){return b.call(a,d)||c.call(a,d);};}return a;})();var a=CKEDITOR;if(!a.event){a.event=function(){};a.event.implementOn=function(b,c){var d=a.event.prototype;for(var e in d){if(b[e]==undefined)b[e]=d[e];}};a.event.prototype=(function(){var b=function(d){var e=d.getPrivate&&d.getPrivate()||d._||(d._={});return e.events||(e.events={});},c=function(d){this.name=d;this.listeners=[];};c.prototype={getListenerIndex:function(d){for(var e=0,f=this.listeners;e=0;n--){if(k[n].priority<=h){k.splice(n+1,0,m);return;}}k.unshift(m);}},fire:(function(){var d=false,e=function(){d=true;},f=false,g=function(){f=true;};return function(h,i,j){var k=b(this)[h],l=d,m=f;d=f=false;if(k){var n=k.listeners;if(n.length){n=n.slice(0);for(var o=0;o=0)f.listeners.splice(g,1);}},hasListeners:function(d){var e=b(this)[d]; +return e&&e.listeners.length>0;}};})();}if(!a.editor){a.ELEMENT_MODE_NONE=0;a.ELEMENT_MODE_REPLACE=1;a.ELEMENT_MODE_APPENDTO=2;a.editor=function(b,c,d,e){var f=this;f._={instanceConfig:b,element:c,data:e};f.elementMode=d||0;a.event.call(f);f._init();};a.editor.replace=function(b,c){var d=b;if(typeof d!='object'){d=document.getElementById(b);if(!d){var e=0,f=document.getElementsByName(b);while((d=f[e++])&&d.tagName.toLowerCase()!='textarea'){}}if(!d)throw '[CKEDITOR.editor.replace] The element with id or name "'+b+'" was not found.';}d.style.visibility='hidden';return new a.editor(c,d,1);};a.editor.appendTo=function(b,c,d){var e=b;if(typeof e!='object'){e=document.getElementById(b);if(!e)throw '[CKEDITOR.editor.appendTo] The element with id "'+b+'" was not found.';}return new a.editor(c,e,2,d);};a.editor.prototype={_init:function(){var b=a.editor._pending||(a.editor._pending=[]);b.push(this);},fire:function(b,c){return a.event.prototype.fire.call(this,b,c,this);},fireOnce:function(b,c){return a.event.prototype.fireOnce.call(this,b,c,this);}};a.event.implementOn(a.editor.prototype,true);}if(!a.env)a.env=(function(){var b=navigator.userAgent.toLowerCase(),c=window.opera,d={ie:/*@cc_on!@*/false,opera:!!c&&c.version,webkit:b.indexOf(' applewebkit/')>-1,air:b.indexOf(' adobeair/')>-1,mac:b.indexOf('macintosh')>-1,quirks:document.compatMode=='BackCompat',mobile:b.indexOf('mobile')>-1,isCustomDomain:function(){if(!this.ie)return false;var g=document.domain,h=window.location.hostname;return g!=h&&g!='['+h+']';}};d.gecko=navigator.product=='Gecko'&&!d.webkit&&!d.opera;var e=0;if(d.ie){e=parseFloat(b.match(/msie (\d+)/)[1]);d.ie8=!!document.documentMode;d.ie8Compat=document.documentMode==8;d.ie7Compat=e==7&&!document.documentMode||document.documentMode==7;d.ie6Compat=e<7||d.quirks;}if(d.gecko){var f=b.match(/rv:([\d\.]+)/);if(f){f=f[1].split('.');e=f[0]*10000+(f[1]||0)*100+ +(f[2]||0);}}if(d.opera)e=parseFloat(c.version());if(d.air)e=parseFloat(b.match(/ adobeair\/(\d+)/)[1]);if(d.webkit)e=parseFloat(b.match(/ applewebkit\/(\d+)/)[1]);d.version=e;d.isCompatible=!d.mobile&&(d.ie&&e>=6||d.gecko&&e>=10801||d.opera&&e>=9.5||d.air&&e>=1||d.webkit&&e>=522||false);d.cssClass='cke_browser_'+(d.ie?'ie':d.gecko?'gecko':d.opera?'opera':d.air?'air':d.webkit?'webkit':'unknown');if(d.quirks)d.cssClass+=' cke_browser_quirks';if(d.ie){d.cssClass+=' cke_browser_ie'+(d.version<7?'6':d.version>=8?'8':'7');if(d.quirks)d.cssClass+=' cke_browser_iequirks';}if(d.gecko&&e<10900)d.cssClass+=' cke_browser_gecko18'; +return d;})();var b=a.env;var c=b.ie;if(a.status=='unloaded')(function(){a.event.implementOn(a);a.loadFullCore=function(){if(a.status!='basic_ready'){a.loadFullCore._load=true;return;}delete a.loadFullCore;var e=document.createElement('script');e.type='text/javascript';e.src=a.basePath+'ckeditor.js';document.getElementsByTagName('head')[0].appendChild(e);};a.loadFullCoreTimeout=0;a.replaceClass='ckeditor';a.replaceByClassEnabled=true;var d=function(e,f,g,h){if(b.isCompatible){if(a.loadFullCore)a.loadFullCore();var i=g(e,f,h);a.add(i);return i;}return null;};a.replace=function(e,f){return d(e,f,a.editor.replace);};a.appendTo=function(e,f,g){return d(e,f,a.editor.appendTo,g);};a.add=function(e){var f=this._.pending||(this._.pending=[]);f.push(e);};a.replaceAll=function(){var e=document.getElementsByTagName('textarea');for(var f=0;f'+g+'');else h.push('');}return h.join('');},htmlEncode:function(f){var g=function(k){var l=new d.element('span');l.setText(k);return l.getHtml();},h=g('\n').toLowerCase()=='
    '?function(k){return g(k).replace(/
    /gi,'\n');}:g,i=g('>')=='>'?function(k){return h(k).replace(/>/g,'>');}:h,j=g(' ')=='  '?function(k){return i(k).replace(/ /g,' ');}:i;this.htmlEncode=j;return this.htmlEncode(f);},htmlEncodeAttr:function(f){return f.replace(/"/g,'"').replace(//g,'>');},escapeCssSelector:function(f){return f.replace(/[\s#:.,$*^\[\]()~=+>]/g,'\\$&');},getNextNumber:(function(){var f=0;return function(){return++f;};})(),getNextId:function(){return 'cke_'+this.getNextNumber();},override:function(f,g){return g(f);},setTimeout:function(f,g,h,i,j){if(!j)j=window;if(!h)h=j;return j.setTimeout(function(){if(i)f.apply(h,[].concat(i));else f.apply(h);},g||0);},trim:(function(){var f=/(?:^[ \t\n\r]+)|(?:[ \t\n\r]+$)/g;return function(g){return g.replace(f,'');};})(),ltrim:(function(){var f=/^[ \t\n\r]+/g;return function(g){return g.replace(f,'');};})(),rtrim:(function(){var f=/[ \t\n\r]+$/g;return function(g){return g.replace(f,'');};})(),indexOf:Array.prototype.indexOf?function(f,g){return f.indexOf(g);}:function(f,g){for(var h=0,i=f.length;h]*>/g,''):i;},getOuterHtml:function(){var j=this;if(j.$.outerHTML)return j.$.outerHTML.replace(/<\?[^>]*>/,'');var i=j.$.ownerDocument.createElement('div');i.appendChild(j.$.cloneNode(true));return i.innerHTML;},setHtml:function(i){return this.$.innerHTML=i;},setText:function(i){h.prototype.setText=this.$.innerText!=undefined?function(j){return this.$.innerText=j;}:function(j){return this.$.textContent=j;};return this.setText(i);},getAttribute:(function(){var i=function(j){return this.$.getAttribute(j,2);};if(c&&(b.ie7Compat||b.ie6Compat))return function(j){var n=this;switch(j){case 'class':j='className';break;case 'tabindex':var k=i.call(n,j);if(k!==0&&n.$.tabIndex===0)k=null;return k;break;case 'checked':var l=n.$.attributes.getNamedItem(j),m=l.specified?l.nodeValue:n.$.checked;return m?'checked':null;case 'hspace':return n.$.hspace;case 'style':return n.$.style.cssText;}return i.call(n,j);};else return i;})(),getChildren:function(){return new d.nodeList(this.$.childNodes);},getComputedStyle:c?function(i){return this.$.currentStyle[e.cssStyleToDomStyle(i)];}:function(i){return this.getWindow().$.getComputedStyle(this.$,'').getPropertyValue(i);},getDtd:function(){var i=f[this.getName()];this.getDtd=function(){return i;};return i;},getElementsByTag:g.prototype.getElementsByTag,getTabIndex:c?function(){var i=this.$.tabIndex;if(i===0&&!f.$tabIndex[this.getName()]&&parseInt(this.getAttribute('tabindex'),10)!==0)i=-1;return i;}:b.webkit?function(){var i=this.$.tabIndex;if(i==undefined){i=parseInt(this.getAttribute('tabindex'),10);if(isNaN(i))i=-1;}return i;}:function(){return this.$.tabIndex;},getText:function(){return this.$.textContent||this.$.innerText||'';},getWindow:function(){return this.getDocument().getWindow();},getId:function(){return this.$.id||null;},getNameAtt:function(){return this.$.name||null;},getName:function(){var i=this.$.nodeName.toLowerCase();if(c){var j=this.$.scopeName;if(j!='HTML')i=j.toLowerCase()+':'+i;}return(this.getName=function(){return i;})();},getValue:function(){return this.$.value;},getFirst:function(i){var j=this.$.firstChild,k=j&&new d.node(j);if(k&&i&&!i(k))k=k.getNext(i);return k;},getLast:function(i){var j=this.$.lastChild,k=j&&new d.node(j);if(k&&i&&!i(k))k=k.getPrevious(i);return k;},getStyle:function(i){return this.$.style[e.cssStyleToDomStyle(i)]; +},is:function(){var i=this.getName();for(var j=0;j0&&(j>2||!k[i[0].nodeName]||j==2&&!k[i[1].nodeName]);},hasAttribute:function(i){var j=this.$.attributes.getNamedItem(i);return!!(j&&j.specified);},hide:function(){this.setStyle('display','none');},moveChildren:function(i,j){var k=this.$;i=i.$;if(k==i)return;var l;if(j)while(l=k.lastChild)i.insertBefore(k.removeChild(l),i.firstChild);else while(l=k.firstChild)i.appendChild(k.removeChild(l));},mergeSiblings:(function(){function i(j,k,l){if(k&&k.type==1){var m=[];while(k.getAttribute('_cke_bookmark')||k.isEmptyInlineRemoveable()){m.push(k);k=l?k.getNext():k.getPrevious();if(!k||k.type!=1)return;}if(j.isIdentical(k)){var n=l?j.getLast():j.getFirst();while(m.length)m.shift().move(j,!l);k.moveChildren(j,!l);k.remove();if(n&&n.type==1)n.mergeSiblings();}}};return function(){var j=this;if(!(f.$removeEmpty[j.getName()]||j.is('a')))return;i(j,j.getNext(),true);i(j,j.getPrevious());};})(),show:function(){this.setStyles({display:'',visibility:''}); +},setAttribute:(function(){var i=function(j,k){this.$.setAttribute(j,k);return this;};if(c&&(b.ie7Compat||b.ie6Compat))return function(j,k){var l=this;if(j=='class')l.$.className=k;else if(j=='style')l.$.style.cssText=k;else if(j=='tabindex')l.$.tabIndex=k;else if(j=='checked')l.$.checked=k;else i.apply(l,arguments);return l;};else return i;})(),setAttributes:function(i){for(var j in i)this.setAttribute(j,i[j]);return this;},setValue:function(i){this.$.value=i;return this;},removeAttribute:(function(){var i=function(j){this.$.removeAttribute(j);};if(c&&(b.ie7Compat||b.ie6Compat))return function(j){if(j=='class')j='className';else if(j=='tabindex')j='tabIndex';i.call(this,j);};else return i;})(),removeAttributes:function(i){if(e.isArray(i))for(var j=0;j=100?'':'progid:DXImageTransform.Microsoft.Alpha(opacity='+i+')');}else this.setStyle('opacity',i);},unselectable:b.gecko?function(){this.$.style.MozUserSelect='none';this.on('dragstart',function(i){i.data.preventDefault();});}:b.webkit?function(){this.$.style.KhtmlUserSelect='none';this.on('dragstart',function(i){i.data.preventDefault();});}:function(){if(c||b.opera){var i=this.$,j,k=0;i.unselectable='on';while(j=i.all[k++])switch(j.tagName.toLowerCase()){case 'iframe':case 'textarea':case 'input':case 'select':break;default:j.unselectable='on';}}},getPositionedAncestor:function(){var i=this;while(i.getName()!='html'){if(i.getComputedStyle('position')!='static')return i;i=i.getParent();}return null;},getDocumentPosition:function(i){var D=this;var j=0,k=0,l=D.getDocument().getBody(),m=D.getDocument().$.compatMode=='BackCompat',n=D.getDocument();if(document.documentElement.getBoundingClientRect){var o=D.$.getBoundingClientRect(),p=n.$,q=p.documentElement,r=q.clientTop||l.$.clientTop||0,s=q.clientLeft||l.$.clientLeft||0,t=true;if(c){var u=n.getDocumentElement().contains(D),v=n.getBody().contains(D);t=m&&v||!m&&u;}if(t){j=o.left+(!m&&q.scrollLeft||l.$.scrollLeft);j-=s;k=o.top+(!m&&q.scrollTop||l.$.scrollTop); +k-=r;}}else{var w=D,x=null,y;while(w&&!(w.getName()=='body'||w.getName()=='html')){j+=w.$.offsetLeft-w.$.scrollLeft;k+=w.$.offsetTop-w.$.scrollTop;if(!w.equals(D)){j+=w.$.clientLeft||0;k+=w.$.clientTop||0;}var z=x;while(z&&!z.equals(w)){j-=z.$.scrollLeft;k-=z.$.scrollTop;z=z.getParent();}x=w;w=(y=w.$.offsetParent)?new h(y):null;}}if(i){var A=D.getWindow(),B=i.getWindow();if(!A.equals(B)&&A.$.frameElement){var C=new h(A.$.frameElement).getDocumentPosition(i);j+=C.x;k+=C.y;}}if(!document.documentElement.getBoundingClientRect)if(b.gecko&&!m){j+=D.$.clientLeft?1:0;k+=D.$.clientTop?1:0;}return{x:j,y:k};},scrollIntoView:function(i){var o=this;var j=o.getWindow(),k=j.getViewPaneSize().height,l=k*-1;if(i)l+=k;else{l+=o.$.offsetHeight||0;l+=parseInt(o.getComputedStyle('marginBottom')||0,10)||0;}var m=o.getDocumentPosition();l+=m.y;l=l<0?0:l;var n=j.getScrollPosition().y;if(l>n||lwindow.setTimeout(function(){window.close();},50);")');}return i&&new g(i.contentWindow.document);},copyAttributes:function(i,j){var p=this;var k=p.$.attributes;j=j||{};for(var l=0;l0&&j)j=j.childNodes[i.shift()];return j?new d.node(j):null;},getChildCount:function(){return this.$.childNodes.length;},disableContextMenu:function(){this.on('contextmenu',function(i){if(!i.data.getTarget().hasClass('cke_enable_context_menu'))i.data.preventDefault();});},setSize:(function(){var i={width:['border-left-width','border-right-width','padding-left','padding-right'],height:['border-top-width','border-bottom-width','padding-top','padding-bottom']}; +return function(j,k,l){if(typeof k=='number'){if(l&&!(c&&b.quirks)){var m=0;for(var n=0,o=i[j].length;n',bodyId:'',bodyClass:'',fullPage:false,height:200,plugins:'about,a11yhelp,basicstyles,bidi,blockquote,button,clipboard,colorbutton,colordialog,contextmenu,dialogadvtab,div,elementspath,enterkey,entities,filebrowser,find,flash,font,format,forms,horizontalrule,htmldataprocessor,image,indent,justify,keystrokes,link,list,liststyle,maximize,newpage,pagebreak,pastefromword,pastetext,popup,preview,print,removeformat,resize,save,scayt,smiley,showblocks,showborders,sourcearea,stylescombo,table,tabletools,specialchar,tab,templates,toolbar,undo,wysiwygarea,wsc',extraPlugins:'',removePlugins:'',protectedSource:[],tabIndex:0,theme:'default',skin:'kama',width:'',baseFloatZIndex:10000};var i=a.config;a.focusManager=function(j){if(j.focusManager)return j.focusManager;this.hasFocus=false;this._={editor:j};return this;};a.focusManager.prototype={focus:function(){var k=this;if(k._.timer)clearTimeout(k._.timer);if(!k.hasFocus){if(a.currentInstance)a.currentInstance.focusManager.forceBlur();var j=k._.editor;j.container.getChild(1).addClass('cke_focus');k.hasFocus=true;j.fire('focus');}},blur:function(){var j=this;if(j._.timer)clearTimeout(j._.timer);j._.timer=setTimeout(function(){delete j._.timer; +j.forceBlur();},100);},forceBlur:function(){if(this.hasFocus){var j=this._.editor;j.container.getChild(1).removeClass('cke_focus');this.hasFocus=false;j.fire('blur');}}};(function(){var j={};a.lang={languages:{af:1,ar:1,bg:1,bn:1,bs:1,ca:1,cs:1,cy:1,da:1,de:1,el:1,'en-au':1,'en-ca':1,'en-gb':1,en:1,eo:1,es:1,et:1,eu:1,fa:1,fi:1,fo:1,'fr-ca':1,fr:1,gl:1,gu:1,he:1,hi:1,hr:1,hu:1,is:1,it:1,ja:1,km:1,ko:1,lt:1,lv:1,mn:1,ms:1,nb:1,nl:1,no:1,pl:1,'pt-br':1,pt:1,ro:1,ru:1,sk:1,sl:1,'sr-latn':1,sr:1,sv:1,th:1,tr:1,uk:1,vi:1,'zh-cn':1,zh:1},load:function(k,l,m){if(!k||!a.lang.languages[k])k=this.detect(l,k);if(!this[k])a.scriptLoader.load(a.getUrl('lang/'+k+'.js'),function(){m(k,this[k]);},this);else m(k,this[k]);},detect:function(k,l){var m=this.languages;l=l||navigator.userLanguage||navigator.language;var n=l.toLowerCase().match(/([a-z]+)(?:-([a-z]+))?/),o=n[1],p=n[2];if(m[o+'-'+p])o=o+'-'+p;else if(!m[o])o=null;a.lang.detect=o?function(){return o;}:function(q){return q;};return o||k;}};})();a.scriptLoader=(function(){var j={},k={};return{load:function(l,m,n,o,p){var q=typeof l=='string';if(q)l=[l];if(!n)n=a;var r=l.length,s=[],t=[],u=function(z){if(m)if(q)m.call(n,z);else m.call(n,s,t);};if(r===0){u(true);return;}var v=function(z,A){(A?s:t).push(z);if(--r<=0){p&&a.document.getDocumentElement().removeStyle('cursor');u(A);}},w=function(z,A){j[z]=1;var B=k[z];delete k[z];for(var C=0;C1)return;var B=new h('script');B.setAttributes({type:'text/javascript',src:z});if(m)if(c)B.$.onreadystatechange=function(){if(B.$.readyState=='loaded'||B.$.readyState=='complete'){B.$.onreadystatechange=null;w(z,true);}};else{B.$.onload=function(){setTimeout(function(){w(z,true);},0);};B.$.onerror=function(){w(z,false);};}B.appendTo(a.document.getHead());};p&&a.document.getDocumentElement().setStyle('cursor','wait');for(var y=0;y0){t(v);a.imageCacher.load(v,function(){l[p]=1;n(o,p,q,r);});return;}l[p]=1;}q=s[q];var w=!q||!!q._isLoaded;if(w)r&&r();else{var x=q._pending||(q._pending=[]);x.push(r);if(x.length>1)return;var y=!q.css||!q.css.length,z=!q.js||!q.js.length,A=function(){if(y&&z){q._isLoaded=1;for(var D=0;D=0?x.langCode:J[0];if(!I.lang[L])G.push(a.getUrl(K+'lang/'+L+'.js'));else{e.extend(x.lang,I.lang[L]);L=null;}}F.push(L);E.push(I);}a.scriptLoader.load(G,function(){var M=['beforeInit','init','afterInit'];for(var N=0;N]+)>)|(?:!--([\\S|\\s]*?)-->)|(?:([^\\s>]+)\\s*((?:(?:[^\"'>]+)|(?:\"[^\"]*\")|(?:'[^']*'))*)\\/?>))",'g')};};(function(){var l=/([\w\-:.]+)(?:(?:\s*=\s*(?:(?:"([^"]*)")|(?:'([^']*)')|([^\s>]+)))|(?=\s|$))/g,m={checked:1,compact:1,declare:1,defer:1,disabled:1,ismap:1,multiple:1,nohref:1,noresize:1,noshade:1,nowrap:1,readonly:1,selected:1};a.htmlParser.prototype={onTagOpen:function(){},onTagClose:function(){},onText:function(){},onCDATA:function(){},onComment:function(){},parse:function(n){var A=this;var o,p,q=0,r;while(o=A._.htmlPartsRegex.exec(n)){var s=o.index;if(s>q){var t=n.substring(q,s);if(r)r.push(t);else A.onText(t);}q=A._.htmlPartsRegex.lastIndex;if(p=o[1]){p=p.toLowerCase();if(r&&f.$cdata[p]){A.onCDATA(r.join(''));r=null;}if(!r){A.onTagClose(p);continue;}}if(r){r.push(o[0]);continue;}if(p=o[3]){p=p.toLowerCase();if(/="/.test(p))continue;var u={},v,w=o[4],x=!!(w&&w.charAt(w.length-1)=='/');if(w)while(v=l.exec(w)){var y=v[1].toLowerCase(),z=v[2]||v[3]||v[4]||''; +if(!z&&m[y])u[y]=y;else u[y]=z;}A.onTagOpen(p,u,x);if(!r&&f.$cdata[p])r=[];continue;}if(p=o[2])A.onComment(p);}if(n.length>q)A.onText(n.substring(q,n.length));}};})();a.htmlParser.comment=function(l){this.value=l;this._={isBlockLike:false};};a.htmlParser.comment.prototype={type:8,writeHtml:function(l,m){var n=this.value;if(m){if(!(n=m.onComment(n,this)))return;if(typeof n!='string'){n.parent=this.parent;n.writeHtml(l,m);return;}}l.comment(n);}};(function(){var l=/[\t\r\n ]{2,}|[\t\r\n]/g;a.htmlParser.text=function(m){this.value=m;this._={isBlockLike:false};};a.htmlParser.text.prototype={type:3,writeHtml:function(m,n){var o=this.value;if(n&&!(o=n.onText(o,this)))return;m.text(o);}};})();(function(){a.htmlParser.cdata=function(l){this.value=l;};a.htmlParser.cdata.prototype={type:3,writeHtml:function(l){l.write(this.value);}};})();a.htmlParser.fragment=function(){this.children=[];this.parent=null;this._={isBlockLike:true,hasInlineStarted:false};};(function(){var l={colgroup:1,dd:1,dt:1,li:1,option:1,p:1,td:1,tfoot:1,th:1,thead:1,tr:1},m=e.extend({table:1,ul:1,ol:1,dl:1},f.table,f.ul,f.ol,f.dl),n=f.$list,o=f.$listItem;a.htmlParser.fragment.fromHtml=function(p,q){var r=new a.htmlParser(),s=[],t=new a.htmlParser.fragment(),u=[],v=[],w=t,x=false,y;function z(E){var F;if(u.length>0)for(var G=0;G0)w.add(v.shift());};function B(E,F,G){F=F||w||t;if(q&&!F.type){var H,I;if(E.attributes&&(I=E.attributes._cke_real_element_type))H=I;else H=E.name;if(H&&!(H in f.$body)&&!(H in f.$nonBodyContent)){var J=w;w=F;r.onTagOpen(q,{});F=w;if(G)w=J;}}if(E._.isBlockLike&&E.name!='pre'){var K=E.children.length,L=E.children[K-1],M;if(L&&L.type==3)if(!(M=e.rtrim(L.value)))E.children.length=K-1;else L.value=M;}F.add(E);if(E.returnPoint){w=E.returnPoint;delete E.returnPoint;}};r.onTagOpen=function(E,F,G){var H=new a.htmlParser.element(E,F);if(H.isUnknown&&G)H.isEmpty=true;if(f.$removeEmpty[E]){u.push(H);return;}else if(E=='pre')x=true;else if(E=='br'&&x){w.add(new a.htmlParser.text('\n'));return;}if(E=='br'){v.push(H);return;}var I=w.name,J=I&&(f[I]||(w._.isBlockLike?f.div:f.span));if(J&&!H.isUnknown&&!w.isUnknown&&!J[E]){var K=false,L;if(E in n&&I in n){var M=w.children,N=M[M.length-1];if(!(N&&N.name in o))B(N=new a.htmlParser.element('li'),w);y=w,L=N;}else if(E==I)B(w,w.parent);else{if(m[I]){if(!y)y=w; +}else{B(w,w.parent,true);if(!l[I])u.unshift(w);}K=true;}if(L)w=L;else w=w.returnPoint||w.parent;if(K){r.onTagOpen.apply(this,arguments);return;}}z(E);A();H.parent=w;H.returnPoint=y;y=0;if(H.isEmpty)B(H);else w=H;};r.onTagClose=function(E){for(var F=u.length-1;F>=0;F--){if(E==u[F].name){u.splice(F,1);return;}}var G=[],H=[],I=w;while(I.type&&I.name!=E){if(!I._.isBlockLike)H.unshift(I);G.push(I);I=I.parent;}if(I.type){for(F=0;F0&&s.children[q-1]||null;if(r){if(p._.isBlockLike&&r.type==3){r.value=e.rtrim(r.value);if(r.value.length===0){s.children.pop();s.add(p);return;}}r.next=p;}p.previous=r;p.parent=s;s.children.push(p);s._.hasInlineStarted=p.type==3||p.type==1&&!p._.isBlockLike;},writeHtml:function(p,q){var r;this.filterChildren=function(){var s=new a.htmlParser.basicWriter();this.writeChildrenHtml.call(this,s,q,true);var t=s.getHtml();this.children=new a.htmlParser.fragment.fromHtml(t).children;r=1;};!this.name&&q&&q.onFragment(this);this.writeChildrenHtml(p,r?null:q);},writeChildrenHtml:function(p,q){for(var r=0;rn?1:0;};a.htmlParser.element.prototype={type:1,add:a.htmlParser.fragment.prototype.add,clone:function(){return new a.htmlParser.element(this.name,this.attributes);},writeHtml:function(m,n){var o=this.attributes,p=this,q=p.name,r,s,t,u;p.filterChildren=function(){if(!u){var z=new a.htmlParser.basicWriter(); +a.htmlParser.fragment.prototype.writeChildrenHtml.call(p,z,n);p.children=new a.htmlParser.fragment.fromHtml(z.getHtml()).children;u=1;}};if(n){for(;;){if(!(q=n.onElementName(q)))return;p.name=q;if(!(p=n.onElement(p)))return;p.parent=this.parent;if(p.name==q)break;if(p.type!=1){p.writeHtml(m,n);return;}q=p.name;if(!q){this.writeChildrenHtml.call(p,m,u?null:n);return;}}o=p.attributes;}m.openTag(q,o);var v=[];for(var w=0;w<2;w++)for(r in o){s=r;t=o[r];if(w==1)v.push([r,t]);else if(n){for(;;){if(!(s=n.onAttributeName(r))){delete o[r];break;}else if(s!=r){delete o[r];r=s;continue;}else break;}if(s)if((t=n.onAttribute(p,s,t))===false)delete o[s];else o[s]=t;}}if(m.sortAttributes)v.sort(l);var x=v.length;for(w=0;w=0;u--){var x=r[u];if(x){x.pri=s;q.splice(t,0,x);}}}};function n(q,r,s){if(r)for(var t in r){var u=q[t];q[t]=o(u,r[t],s);if(!u)q.$length++;}};function o(q,r,s){if(r){r.pri=s;if(q){if(!q.splice){if(q.pri>s)q=[r,q];else q=[q,r];q.filter=p;}else m(q,r,s);return q;}else{r.filter=r;return r;}}};function p(q){var r=q.type||q instanceof a.htmlParser.fragment;for(var s=0;s');else this._.output.push('>');},attribute:function(l,m){if(typeof m=='string')m=e.htmlEncodeAttr(m);this._.output.push(' ',l,'="',m,'"');},closeTag:function(l){this._.output.push('');},text:function(l){this._.output.push(l);},comment:function(l){this._.output.push('');},write:function(l){this._.output.push(l);},reset:function(){this._.output=[];this._.indent=false;},getHtml:function(l){var m=this._.output.join('');if(l)this.reset();return m;}}});delete a.loadFullCore;a.instances={};a.document=new g(document);a.add=function(l){a.instances[l.name]=l;l.on('focus',function(){if(a.currentInstance!=l){a.currentInstance=l;a.fire('currentInstance');}});l.on('blur',function(){if(a.currentInstance==l){a.currentInstance=null;a.fire('currentInstance');}});};a.remove=function(l){delete a.instances[l.name];};a.on('instanceDestroyed',function(){if(e.isEmpty(this.instances))a.fire('reset');});a.TRISTATE_ON=1;a.TRISTATE_OFF=2;a.TRISTATE_DISABLED=0;d.comment=e.createClass({base:d.node,$:function(l,m){if(typeof l=='string')l=(m?m.$:document).createComment(l);this.base(l);},proto:{type:8,getOuterHtml:function(){return '';}}});(function(){var l={address:1,blockquote:1,dl:1,h1:1,h2:1,h3:1,h4:1,h5:1,h6:1,p:1,pre:1,li:1,dt:1,dd:1},m={body:1,div:1,table:1,tbody:1,tr:1,td:1,th:1,caption:1,form:1},n=function(o){var p=o.getChildren();for(var q=0,r=p.count();q0&&D.getChild(w.startOffset-1);this._.guardRTL=function(G,H){return(!H||!D.equals(G))&&(!E||!G.equals(E))&&(G.type!=1||!H||G.getName()!='body');};}var F=t?this._.guardRTL:this._.guardLTR;if(y)x=function(G,H){if(F(G,H)===false)return false;return y(G,H);};else x=F;if(this.current)v=this.current[A](false,z,x);else if(t){v=w.endContainer;if(w.endOffset>0){v=v.getChild(w.endOffset-1);if(x(v)===false)v=null;}else v=x(v,true)===false?null:v.getPreviousSourceNode(true,z,x);}else{v=w.startContainer; +v=v.getChild(w.startOffset);if(v){if(x(v)===false)v=null;}else v=x(w.startContainer,true)===false?null:w.startContainer.getNextSourceNode(true,z,x);}while(v&&!this._.end){this.current=v;if(!this.evaluator||this.evaluator(v)!==false){if(!u)return v;}else if(u&&this.evaluator)return false;v=v[A](false,z,x);}this.end();return this.current=null;};function m(t){var u,v=null;while(u=l.call(this,t))v=u;return v;};d.walker=e.createClass({$:function(t){this.range=t;this._={};},proto:{end:function(){this._.end=1;},next:function(){return l.call(this);},previous:function(){return l.call(this,true);},checkForward:function(){return l.call(this,false,true)!==false;},checkBackward:function(){return l.call(this,true,true)!==false;},lastForward:function(){return m.call(this);},lastBackward:function(){return m.call(this,true);},reset:function(){delete this.current;this._={};}}});var n={block:1,'list-item':1,table:1,'table-row-group':1,'table-header-group':1,'table-footer-group':1,'table-row':1,'table-column-group':1,'table-column':1,'table-cell':1,'table-caption':1},o={hr:1};h.prototype.isBlockBoundary=function(t){var u=e.extend({},o,t||{});return n[this.getComputedStyle('display')]||u[this.getName()];};d.walker.blockBoundary=function(t){return function(u,v){return!(u.type==1&&u.isBlockBoundary(t));};};d.walker.listItemBoundary=function(){return this.blockBoundary({br:1});};d.walker.bookmark=function(t,u){function v(w){return w&&w.getName&&w.getName()=='span'&&w.hasAttribute('_cke_bookmark');};return function(w){var x,y;x=w&&!w.getName&&(y=w.getParent())&&v(y);x=t?x:x||v(w);return u^x;};};d.walker.whitespaces=function(t){return function(u){var v=u&&u.type==3&&!e.trim(u.getText());return t^v;};};d.walker.invisible=function(t){var u=d.walker.whitespaces();return function(v){var w=u(v)||v.is&&!v.$.offsetHeight;return t^w;};};var p=/^[\t\r\n ]*(?: |\xa0)$/,q=d.walker.whitespaces(true),r=d.walker.bookmark(false,true),s=function(t){return r(t)&&q(t);};h.prototype.getBogus=function(){var t=this.getLast(s);if(t&&(!c?t.is&&t.is('br'):t.getText&&p.test(t.getText())))return t;return false;};})();d.range=function(l){var m=this;m.startContainer=null;m.startOffset=null;m.endContainer=null;m.endOffset=null;m.collapsed=true;m.document=l;};(function(){var l=function(t){t.collapsed=t.startContainer&&t.endContainer&&t.startContainer.equals(t.endContainer)&&t.startOffset==t.endOffset;},m=function(t,u,v){t.optimizeBookmark();var w=t.startContainer,x=t.endContainer,y=t.startOffset,z=t.endOffset,A,B; +if(x.type==3)x=x.split(z);else if(x.getChildCount()>0)if(z>=x.getChildCount()){x=x.append(t.document.createText(''));B=true;}else x=x.getChild(z);if(w.type==3){w.split(y);if(w.equals(x))x=w.getNext();}else if(!y){w=w.getFirst().insertBeforeMe(t.document.createText(''));A=true;}else if(y>=w.getChildCount()){w=w.append(t.document.createText(''));A=true;}else w=w.getChild(y).getPrevious();var C=w.getParents(),D=x.getParents(),E,F,G;for(E=0;E0&&!I.equals(x))J=H.append(I.clone());if(!C[N]||I.$.parentNode!=C[N].$.parentNode){K=I.getPrevious();while(K){if(K.equals(C[N])||K.equals(w))break;L=K.getPrevious();if(u==2)H.$.insertBefore(K.$.cloneNode(true),H.$.firstChild);else{K.remove();if(u==1)H.$.insertBefore(K.$,H.$.firstChild);}K=L;}}if(H)H=J;}if(u==2){var O=t.startContainer;if(O.type==3){O.$.data+=O.$.nextSibling.data;O.$.parentNode.removeChild(O.$.nextSibling);}var P=t.endContainer;if(P.type==3&&P.$.nextSibling){P.$.data+=P.$.nextSibling.data;P.$.parentNode.removeChild(P.$.nextSibling);}}else{if(F&&G&&(w.$.parentNode!=F.$.parentNode||x.$.parentNode!=G.$.parentNode)){var Q=G.getIndex();if(A&&G.$.parentNode==w.$.parentNode)Q--;t.setStart(G.getParent(),Q);}t.collapse(true);}if(A)w.remove();if(B&&x.$.parentNode)x.remove();},n={abbr:1,acronym:1,b:1,bdo:1,big:1,cite:1,code:1,del:1,dfn:1,em:1,font:1,i:1,ins:1,label:1,kbd:1,q:1,samp:1,small:1,span:1,strike:1,strong:1,sub:1,sup:1,tt:1,u:1,'var':1};function o(t){var u=false,v=d.walker.bookmark(true);return function(w){if(v(w))return true;if(w.type==3){if(e.trim(w.getText()).length)return false;}else if(w.type==1)if(!n[w.getName()])if(!t&&!c&&w.getName()=='br'&&!u)u=true;else return false;return true;};};function p(t){return t.type!=3&&t.getName() in f.$removeEmpty||!e.trim(t.getText())||t.getParent().hasAttribute('_cke_bookmark');};var q=new d.walker.whitespaces(),r=new d.walker.bookmark();function s(t){return!q(t)&&!r(t);};d.range.prototype={clone:function(){var u=this;var t=new d.range(u.document);t.startContainer=u.startContainer;t.startOffset=u.startOffset;t.endContainer=u.endContainer;t.endOffset=u.endOffset;t.collapsed=u.collapsed;return t;},collapse:function(t){var u=this;if(t){u.endContainer=u.startContainer; +u.endOffset=u.startOffset;}else{u.startContainer=u.endContainer;u.startOffset=u.endOffset;}u.collapsed=true;},cloneContents:function(){var t=new d.documentFragment(this.document);if(!this.collapsed)m(this,2,t);return t;},deleteContents:function(){if(this.collapsed)return;m(this,0);},extractContents:function(){var t=new d.documentFragment(this.document);if(!this.collapsed)m(this,1,t);return t;},createBookmark:function(t){var z=this;var u,v,w,x,y=z.collapsed;u=z.document.createElement('span');u.setAttribute('_cke_bookmark',1);u.setStyle('display','none');u.setHtml(' ');if(t){w='cke_bm_'+e.getNextNumber();u.setAttribute('id',w+'S');}if(!y){v=u.clone();v.setHtml(' ');if(t)v.setAttribute('id',w+'E');x=z.clone();x.collapse();x.insertNode(v);}x=z.clone();x.collapse(true);x.insertNode(u);if(v){z.setStartAfter(u);z.setEndBefore(v);}else z.moveToPosition(u,4);return{startNode:t?w+'S':u,endNode:t?w+'E':v,serializable:t,collapsed:y};},createBookmark2:function(t){var B=this;var u=B.startContainer,v=B.endContainer,w=B.startOffset,x=B.endOffset,y=B.collapsed,z,A;if(!u||!v)return{start:0,end:0};if(t){if(u.type==1){z=u.getChild(w);if(z&&z.type==3&&w>0&&z.getPrevious().type==3){u=z;w=0;}}while(u.type==3&&(A=u.getPrevious())&&A.type==3){u=A;w+=A.getLength();}if(!y){if(v.type==1){z=v.getChild(x);if(z&&z.type==3&&x>0&&z.getPrevious().type==3){v=z;x=0;}}while(v.type==3&&(A=v.getPrevious())&&A.type==3){v=A;x+=A.getLength();}}}return{start:u.getAddress(t),end:y?null:v.getAddress(t),startOffset:w,endOffset:x,normalized:t,collapsed:y,is2:true};},moveToBookmark:function(t){var B=this;if(t.is2){var u=B.document.getByAddress(t.start,t.normalized),v=t.startOffset,w=t.end&&B.document.getByAddress(t.end,t.normalized),x=t.endOffset;B.setStart(u,v);if(w)B.setEnd(w,x);else B.collapse(true);}else{var y=t.serializable,z=y?B.document.getById(t.startNode):t.startNode,A=y?B.document.getById(t.endNode):t.endNode;B.setStartBefore(z);z.remove();if(A){B.setEndBefore(A);A.remove();}else B.collapse(true);}},getBoundaryNodes:function(){var y=this;var t=y.startContainer,u=y.endContainer,v=y.startOffset,w=y.endOffset,x;if(t.type==1){x=t.getChildCount();if(x>v)t=t.getChild(v);else if(x<1)t=t.getPreviousSourceNode();else{t=t.$;while(t.lastChild)t=t.lastChild;t=new d.node(t);t=t.getNextSourceNode()||t;}}if(u.type==1){x=u.getChildCount();if(x>w)u=u.getChild(w).getPreviousSourceNode(true);else if(x<1)u=u.getPreviousSourceNode();else{u=u.$;while(u.lastChild)u=u.lastChild;u=new d.node(u);}}if(t.getPosition(u)&2)t=u; +return{startNode:t,endNode:u};},getCommonAncestor:function(t,u){var y=this;var v=y.startContainer,w=y.endContainer,x;if(v.equals(w)){if(t&&v.type==1&&y.startOffset==y.endOffset-1)x=v.getChild(y.startOffset);else x=v;}else x=v.getCommonAncestor(w);return u&&!x.is?x.getParent():x;},optimize:function(){var v=this;var t=v.startContainer,u=v.startOffset;if(t.type!=1)if(!u)v.setStartBefore(t);else if(u>=t.getLength())v.setStartAfter(t);t=v.endContainer;u=v.endOffset;if(t.type!=1)if(!u)v.setEndBefore(t);else if(u>=t.getLength())v.setEndAfter(t);},optimizeBookmark:function(){var v=this;var t=v.startContainer,u=v.endContainer;if(t.is&&t.is('span')&&t.hasAttribute('_cke_bookmark'))v.setStartAt(t,3);if(u&&u.is&&u.is('span')&&u.hasAttribute('_cke_bookmark'))v.setEndAt(u,4);},trim:function(t,u){var B=this;var v=B.startContainer,w=B.startOffset,x=B.collapsed;if((!t||x)&&v&&v.type==3){if(!w){w=v.getIndex();v=v.getParent();}else if(w>=v.getLength()){w=v.getIndex()+1;v=v.getParent();}else{var y=v.split(w);w=v.getIndex()+1;v=v.getParent();if(B.startContainer.equals(B.endContainer))B.setEnd(y,B.endOffset-B.startOffset);else if(v.equals(B.endContainer))B.endOffset+=1;}B.setStart(v,w);if(x){B.collapse(true);return;}}var z=B.endContainer,A=B.endOffset;if(!(u||x)&&z&&z.type==3){if(!A){A=z.getIndex();z=z.getParent();}else if(A>=z.getLength()){A=z.getIndex()+1;z=z.getParent();}else{z.split(A);A=z.getIndex()+1;z=z.getParent();}B.setEnd(z,A);}},enlarge:function(t){switch(t){case 1:if(this.collapsed)return;var u=this.getCommonAncestor(),v=this.document.getBody(),w,x,y,z,A,B=false,C,D,E=this.startContainer,F=this.startOffset;if(E.type==3){if(F){E=!e.trim(E.substring(0,F)).length&&E;B=!!E;}if(E)if(!(z=E.getPrevious()))y=E.getParent();}else{if(F)z=E.getChild(F-1)||E.getLast();if(!z)y=E;}while(y||z){if(y&&!z){if(!A&&y.equals(u))A=true;if(!v.contains(y))break;if(!B||y.getComputedStyle('display')!='inline'){B=false;if(A)w=y;else this.setStartBefore(y);}z=y.getPrevious();}while(z){C=false;if(z.type==3){D=z.getText();if(/[^\s\ufeff]/.test(D))z=null;C=/[\s\ufeff]$/.test(D);}else if(z.$.offsetWidth>0&&!z.getAttribute('_cke_bookmark'))if(B&&f.$removeEmpty[z.getName()]){D=z.getText();if(/[^\s\ufeff]/.test(D))z=null;else{var G=z.$.all||z.$.getElementsByTagName('*');for(var H=0,I;I=G[H++];){if(!f.$removeEmpty[I.nodeName.toLowerCase()]){z=null;break;}}}if(z)C=!!D.length;}else z=null;if(C)if(B){if(A)w=y;else if(y)this.setStartBefore(y);}else B=true;if(z){var J=z.getPrevious();if(!y&&!J){y=z;z=null;break; +}z=J;}else y=null;}if(y)y=y.getParent();}E=this.endContainer;F=this.endOffset;y=z=null;A=B=false;if(E.type==3){E=!e.trim(E.substring(F)).length&&E;B=!(E&&E.getLength());if(E)if(!(z=E.getNext()))y=E.getParent();}else{z=E.getChild(F);if(!z)y=E;}while(y||z){if(y&&!z){if(!A&&y.equals(u))A=true;if(!v.contains(y))break;if(!B||y.getComputedStyle('display')!='inline'){B=false;if(A)x=y;else if(y)this.setEndAfter(y);}z=y.getNext();}while(z){C=false;if(z.type==3){D=z.getText();if(/[^\s\ufeff]/.test(D))z=null;C=/^[\s\ufeff]/.test(D);}else if(z.$.offsetWidth>0&&!z.getAttribute('_cke_bookmark'))if(B&&f.$removeEmpty[z.getName()]){D=z.getText();if(/[^\s\ufeff]/.test(D))z=null;else{G=z.$.all||z.$.getElementsByTagName('*');for(H=0;I=G[H++];){if(!f.$removeEmpty[I.nodeName.toLowerCase()]){z=null;break;}}}if(z)C=!!D.length;}else z=null;if(C)if(B)if(A)x=y;else this.setEndAfter(y);if(z){J=z.getNext();if(!y&&!J){y=z;z=null;break;}z=J;}else y=null;}if(y)y=y.getParent();}if(w&&x){u=w.contains(x)?x:w;this.setStartBefore(u);this.setEndAfter(u);}break;case 2:case 3:var K=new d.range(this.document);v=this.document.getBody();K.setStartAt(v,1);K.setEnd(this.startContainer,this.startOffset);var L=new d.walker(K),M,N,O=d.walker.blockBoundary(t==3?{br:1}:null),P=function(R){var S=O(R);if(!S)M=R;return S;},Q=function(R){var S=P(R);if(!S&&R.is&&R.is('br'))N=R;return S;};L.guard=P;y=L.lastBackward();M=M||v;this.setStartAt(M,!M.is('br')&&(!y&&this.checkStartOfBlock()||y&&M.contains(y))?1:4);K=this.clone();K.collapse();K.setEndAt(v,2);L=new d.walker(K);L.guard=t==3?Q:P;M=null;y=L.lastForward();M=M||v;this.setEndAt(M,!y&&this.checkEndOfBlock()||y&&M.contains(y)?2:3);if(N)this.setEndAfter(N);}},shrink:function(t,u){if(!this.collapsed){t=t||2;var v=this.clone(),w=this.startContainer,x=this.endContainer,y=this.startOffset,z=this.endOffset,A=this.collapsed,B=1,C=1;if(w&&w.type==3)if(!y)v.setStartBefore(w);else if(y>=w.getLength())v.setStartAfter(w);else{v.setStartBefore(w);B=0;}if(x&&x.type==3)if(!z)v.setEndBefore(x);else if(z>=x.getLength())v.setEndAfter(x);else{v.setEndAfter(x);C=0;}var D=new d.walker(v);D.evaluator=function(H){return H.type==(t==1?1:3);};var E;D.guard=function(H,I){if(t==1&&H.type==3)return false;if(I&&H.equals(E))return false;if(!I&&H.type==1)E=H;return true;};if(B){var F=D[t==1?'lastForward':'next']();F&&this.setStartAt(F,u?1:3);}if(C){D.reset();var G=D[t==1?'lastBackward':'previous']();G&&this.setEndAt(G,u?2:4);}return!!(B||C);}},insertNode:function(t){var x=this;x.optimizeBookmark(); +x.trim(false,true);var u=x.startContainer,v=x.startOffset,w=u.getChild(v);if(w)t.insertBefore(w);else u.append(t);if(t.getParent().equals(x.endContainer))x.endOffset++;x.setStartBefore(t);},moveToPosition:function(t,u){this.setStartAt(t,u);this.collapse(true);},selectNodeContents:function(t){this.setStart(t,0);this.setEnd(t,t.type==3?t.getLength():t.getChildCount());},setStart:function(t,u){var v=this;if(t.type==1&&f.$empty[t.getName()])t=t.getParent(),u=t.getIndex();v.startContainer=t;v.startOffset=u;if(!v.endContainer){v.endContainer=t;v.endOffset=u;}l(v);},setEnd:function(t,u){var v=this;if(t.type==1&&f.$empty[t.getName()])t=t.getParent(),u=t.getIndex()+1;v.endContainer=t;v.endOffset=u;if(!v.startContainer){v.startContainer=t;v.startOffset=u;}l(v);},setStartAfter:function(t){this.setStart(t.getParent(),t.getIndex()+1);},setStartBefore:function(t){this.setStart(t.getParent(),t.getIndex());},setEndAfter:function(t){this.setEnd(t.getParent(),t.getIndex()+1);},setEndBefore:function(t){this.setEnd(t.getParent(),t.getIndex());},setStartAt:function(t,u){var v=this;switch(u){case 1:v.setStart(t,0);break;case 2:if(t.type==3)v.setStart(t,t.getLength());else v.setStart(t,t.getChildCount());break;case 3:v.setStartBefore(t);break;case 4:v.setStartAfter(t);}l(v);},setEndAt:function(t,u){var v=this;switch(u){case 1:v.setEnd(t,0);break;case 2:if(t.type==3)v.setEnd(t,t.getLength());else v.setEnd(t,t.getChildCount());break;case 3:v.setEndBefore(t);break;case 4:v.setEndAfter(t);}l(v);},fixBlock:function(t,u){var x=this;var v=x.createBookmark(),w=x.document.createElement(u);x.collapse(t);x.enlarge(2);x.extractContents().appendTo(w);w.trim();if(!c)w.appendBogus();x.insertNode(w);x.moveToBookmark(v);return w;},splitBlock:function(t){var D=this;var u=new d.elementPath(D.startContainer),v=new d.elementPath(D.endContainer),w=u.blockLimit,x=v.blockLimit,y=u.block,z=v.block,A=null;if(!w.equals(x))return null;if(t!='br'){if(!y){y=D.fixBlock(true,t);z=new d.elementPath(D.endContainer).block;}if(!z)z=D.fixBlock(false,t);}var B=y&&D.checkStartOfBlock(),C=z&&D.checkEndOfBlock();D.deleteContents();if(y&&y.equals(z))if(C){A=new d.elementPath(D.startContainer);D.moveToPosition(z,4);z=null;}else if(B){A=new d.elementPath(D.startContainer);D.moveToPosition(y,3);y=null;}else{z=D.splitElement(y);if(!c&&!y.is('ul','ol'))y.appendBogus();}return{previousBlock:y,nextBlock:z,wasStartOfBlock:B,wasEndOfBlock:C,elementPath:A};},splitElement:function(t){var w=this;if(!w.collapsed)return null;w.setEndAt(t,2); +var u=w.extractContents(),v=t.clone(false);u.appendTo(v);v.insertAfter(t);w.moveToPosition(t,4);return v;},checkBoundaryOfElement:function(t,u){var v=u==1,w=this.clone();w.collapse(v);w[v?'setStartAt':'setEndAt'](t,v?1:2);var x=new d.walker(w);x.evaluator=p;return x[v?'checkBackward':'checkForward']();},checkStartOfBlock:function(){var z=this;var t=z.startContainer,u=z.startOffset;if(u&&t.type==3){var v=e.ltrim(t.substring(0,u));if(v.length)return false;}z.trim();var w=new d.elementPath(z.startContainer),x=z.clone();x.collapse(true);x.setStartAt(w.block||w.blockLimit,1);var y=new d.walker(x);y.evaluator=o(true);return y.checkBackward();},checkEndOfBlock:function(){var z=this;var t=z.endContainer,u=z.endOffset;if(t.type==3){var v=e.rtrim(t.substring(u));if(v.length)return false;}z.trim();var w=new d.elementPath(z.endContainer),x=z.clone();x.collapse(false);x.setEndAt(w.block||w.blockLimit,2);var y=new d.walker(x);y.evaluator=o(false);return y.checkForward();},moveToElementEditablePosition:function(t,u){var v;if(f.$empty[t.getName()])return false;while(t&&t.type==1){v=t.isEditable();if(v)this.moveToPosition(t,u?2:1);else if(f.$inline[t.getName()]){this.moveToPosition(t,u?4:3);return true;}if(f.$empty[t.getName()])t=t[u?'getPrevious':'getNext'](s);else t=t[u?'getLast':'getFirst'](s);if(t&&t.type==3){this.moveToPosition(t,u?4:3);return true;}}return v;},moveToElementEditStart:function(t){return this.moveToElementEditablePosition(t);},moveToElementEditEnd:function(t){return this.moveToElementEditablePosition(t,true);},getEnclosedNode:function(){var t=this.clone();t.optimize();if(t.startContainer.type!=1||t.endContainer.type!=1)return null;var u=new d.walker(t),v=d.walker.bookmark(true),w=d.walker.whitespaces(true),x=function(z){return w(z)&&v(z);};t.evaluator=x;var y=u.next();u.reset();return y&&y.equals(u.previous())?y:null;},getTouchedStartNode:function(){var t=this.startContainer;if(this.collapsed||t.type!=1)return t;return t.getChild(this.startOffset)||t;},getTouchedEndNode:function(){var t=this.endContainer;if(this.collapsed||t.type!=1)return t;return t.getChild(this.endOffset-1)||t;}};})();a.POSITION_AFTER_START=1;a.POSITION_BEFORE_END=2;a.POSITION_BEFORE_START=3;a.POSITION_AFTER_END=4;a.ENLARGE_ELEMENT=1;a.ENLARGE_BLOCK_CONTENTS=2;a.ENLARGE_LIST_ITEM_CONTENTS=3;a.START=1;a.END=2;a.STARTEND=3;a.SHRINK_ELEMENT=1;a.SHRINK_TEXT=2;(function(){d.rangeList=function(n){if(n instanceof d.rangeList)return n;if(!n)n=[];else if(n instanceof d.range)n=[n];return e.extend(n,l); +};var l={createIterator:function(){var n=this,o=[],p;return{getNextRange:function(){p=p==undefined?0:p+1;var q=n[p];if(q&&n.length>1)if(!p)for(var r=n.length-1;r>0;r--)o.unshift(n[r].createBookmark(true));else q.moveToBookmark(o.shift());return q;}};},createBookmarks:function(n){var s=this;var o=[],p;for(var q=0;q',a.document);o.appendTo(a.document.getHead());try{b.hc=o.getComputedStyle('background-image')=='none';}catch(p){b.hc=false;}if(b.hc)b.cssClass+=' cke_hc';o.remove();})();j.load(i.corePlugins.split(','),function(){a.status='loaded';a.fire('loaded');var l=a._.pending;if(l){delete a._.pending;for(var m=0;m=0;A--){var B=[],C=new d.walker(v[A]);C.evaluator=function(G){return G.type==1&&G.getName() in l&&!(G.getName()==(u==1)?'p':'div'&&G.getParent().type==1&&G.getParent().getName()=='blockquote');};while(z=C.next()){o(z,r,s);B.push(z);}y=v[A].createIterator();y.enlargeBr=u!=2;while(z=y.getNextParagraph(u==1?'p':'div')){if(z.isReadOnly())continue;var D=0;for(var E=0;E0){y=z.shift();while(!y.getParent().equals(C))y=y.getParent(); +if(!y.equals(G))D.push(y);G=y;}while(D.length>0){y=D.shift();if(y.getName()=='blockquote'){var H=new d.documentFragment(p.document);while(y.getFirst()){H.append(y.getFirst().remove());z.push(H.getLast());}H.replace(y);}else z.push(y);}var I=p.document.createElement('blockquote');I.insertBefore(z[0]);while(z.length>0){y=z.shift();I.append(y);}}else if(q==1){var J=[],K={};while(y=x.getNextParagraph()){var L=null,M=null;while(y.getParent()){if(y.getParent().getName()=='blockquote'){L=y.getParent();M=y;break;}y=y.getParent();}if(L&&M&&!M.getCustomData('blockquote_moveout')){J.push(M);h.setMarker(K,M,'blockquote_moveout',true);}}h.clearAllMarkers(K);var N=[],O=[];K={};while(J.length>0){var P=J.shift();I=P.getParent();if(!P.getPrevious())P.remove().insertBefore(I);else if(!P.getNext())P.remove().insertAfter(I);else{P.breakParent(P.getParent());O.push(P.getNext());}if(!I.getCustomData('blockquote_processed')){O.push(I);h.setMarker(K,I,'blockquote_processed',true);}N.push(P);}h.clearAllMarkers(K);for(E=O.length-1;E>=0;E--){I=O[E];if(n(I))I.remove();}if(p.config.enterMode==2){var Q=true;while(N.length){P=N.shift();if(P.getName()=='div'){H=new d.documentFragment(p.document);var R=Q&&P.getPrevious()&&!(P.getPrevious().type==1&&P.getPrevious().isBlockBoundary());if(R)H.append(p.document.createElement('br'));var S=P.getNext()&&!(P.getNext().type==1&&P.getNext().isBlockBoundary());while(P.getFirst())P.getFirst().remove().appendTo(H);if(S)H.append(p.document.createElement('br'));H.replace(P);Q=false;}}}}r.selectBookmarks(t);p.focus();}};j.add('blockquote',{init:function(p){p.addCommand('blockquote',o);p.ui.addButton('Blockquote',{label:p.lang.blockquote,command:'blockquote'});p.on('selectionChange',m);},requires:['domiterator']});})();j.add('button',{beforeInit:function(l){l.ui.addHandler(1,k.button.handler);}});a.UI_BUTTON=1;k.button=function(l){e.extend(this,l,{title:l.label,className:l.className||l.command&&'cke_button_'+l.command||'',click:l.click||(function(m){m.execCommand(l.command);})});this._={};};k.button.handler={create:function(l){return new k.button(l);}};k.button.prototype={canGroup:true,render:function(l,m){var n=b,o=this._.id='cke_'+e.getNextNumber(),p='',q=this.command,r,s;this._.editor=l;var t={id:o,button:this,editor:l,focus:function(){var v=a.document.getById(o);v.focus();},execute:function(){this.button.click(l);}};t.clickFn=r=e.addFunction(t.execute,t);t.index=s=k.button._.instances.push(t)-1;if(this.modes)l.on('mode',function(){this.setState(this.modes[l.mode]?2:0); +},this);else if(q){q=l.getCommand(q);if(q){q.on('state',function(){this.setState(q.state);},this);p+='cke_'+(q.state==1?'on':q.state==0?'disabled':'off');}}if(!q)p+='cke_off';if(this.className)p+=' '+this.className;m.push('','=10900&&!n.hc?'':'" href="javascript:void(\''+(this.title||'').replace("'",'')+"')\"",' title="',this.title,'" tabindex="-1" hidefocus="true" role="button" aria-labelledby="'+o+'_label"'+(this.hasArrow?' aria-haspopup="true"':''));if(n.opera||n.gecko&&n.mac)m.push(' onkeypress="return false;"');if(n.gecko)m.push(' onblur="this.style.cssText = this.style.cssText;"');m.push(' onkeydown="return CKEDITOR.ui.button._.keydown(',s,', event);" onfocus="return CKEDITOR.ui.button._.focus(',s,', event);" onclick="CKEDITOR.tools.callFunction(',r,', this); return false;"> ',this.label,'');if(this.hasArrow)m.push(''+(b.hc?'▼':' ')+'');m.push('','');if(this.onRender)this.onRender();return t;},setState:function(l){if(this._.state==l)return false;this._.state=l;var m=a.document.getById(this._.id);if(m){m.setState(l);l==0?m.setAttribute('aria-disabled',true):m.removeAttribute('aria-disabled');l==1?m.setAttribute('aria-pressed',true):m.removeAttribute('aria-pressed');return true;}else return false;}};k.button._={instances:[],keydown:function(l,m){var n=k.button._.instances[l];if(n.onkey){m=new d.event(m);return n.onkey(n,m.getKeystroke())!==false;}},focus:function(l,m){var n=k.button._.instances[l],o;if(n.onfocus)o=n.onfocus(n,new d.event(m))!==false;if(b.gecko&&b.version<10900)m.preventBubble();return o;}};k.prototype.addButton=function(l,m){this.add(l,1,m);};a.on('reset',function(){k.button._.instances=[];});(function(){var l=function(s,t){var u=s.document,v=u.getBody(),w=false,x=function(){w=true;};v.on(t,x);(b.version>7?u.$:u.$.selection.createRange()).execCommand(t);v.removeListener(t,x);return w;},m=c?function(s,t){return l(s,t);}:function(s,t){try{return s.document.$.execCommand(t);}catch(u){return false;}},n=function(s){this.type=s;this.canUndo=this.type=='cut';};n.prototype={exec:function(s,t){this.type=='cut'&&r(s);var u=m(s,this.type);if(!u)alert(s.lang.clipboard[this.type+'Error']); +return u;}};var o={canUndo:false,exec:c?function(s){s.focus();if(!s.document.getBody().fire('beforepaste')&&!l(s,'paste')){s.fire('pasteDialog');return false;}}:function(s){try{if(!s.document.getBody().fire('beforepaste')&&!s.document.$.execCommand('Paste',false,null))throw 0;}catch(t){setTimeout(function(){s.fire('pasteDialog');},0);return false;}}},p=function(s){if(this.mode!='wysiwyg')return;switch(s.data.keyCode){case 1000+86:case 2000+45:var t=this.document.getBody();if(!c&&t.fire('beforepaste'))s.cancel();else if(b.opera||b.gecko&&b.version<10900)t.fire('paste');return;case 1000+88:case 2000+46:var u=this;this.fire('saveSnapshot');setTimeout(function(){u.fire('saveSnapshot');},0);}};function q(s,t,u){var v=this.document;if(c&&v.getById('cke_pastebin'))return;if(t=='text'&&s.data&&s.data.$.clipboardData){var w=s.data.$.clipboardData.getData('text/plain');if(w){s.data.preventDefault();u(w);return;}}var x=this.getSelection(),y=new d.range(v),z=new h(t=='text'?'textarea':b.webkit?'body':'div',v);z.setAttribute('id','cke_pastebin');b.webkit&&z.append(v.createText('\xa0'));v.getBody().append(z);z.setStyles({position:'absolute',top:x.getStartElement().getDocumentPosition().y+'px',width:'1px',height:'1px',overflow:'hidden'});z.setStyle(this.config.contentsLangDirection=='ltr'?'left':'right','-1000px');var A=x.createBookmarks();if(t=='text'){if(c){var B=v.getBody().$.createTextRange();B.moveToElementText(z.$);B.execCommand('Paste');s.data.preventDefault();}else{v.$.designMode='off';z.$.focus();}}else{y.setStartAt(z,1);y.setEndAt(z,2);y.select(true);}window.setTimeout(function(){t=='text'&&!c&&(v.$.designMode='on');z.remove();var C;z=b.webkit&&(C=z.getFirst())&&C.is&&C.hasClass('Apple-style-span')?C:z;x.selectBookmarks(A);u(z['get'+(t=='text'?'Value':'Html')]());},0);};function r(s){if(!c||s.document.$.compatMode=='BackCompat')return;var t=s.getSelection(),u;if(t.getType()==3&&(u=t.getSelectedElement())){var v=t.getRanges()[0],w=s.document.createText('');w.insertBefore(u);v.setStartBefore(w);v.setEndAfter(u);t.selectRanges([v]);setTimeout(function(){if(u.getParent()){w.remove();t.selectElement(u);}},0);}};j.add('clipboard',{requires:['dialog','htmldataprocessor'],init:function(s){s.on('paste',function(x){var y=x.data;if(y.html)s.insertHtml(y.html);else if(y.text)s.insertText(y.text);},null,null,1000);s.on('pasteDialog',function(x){setTimeout(function(){s.openDialog('paste');},0);});function t(x,y,z,A){var B=s.lang[y];s.addCommand(y,z);s.ui.addButton(x,{label:B,command:y}); +if(s.addMenuItems)s.addMenuItem(y,{label:B,command:y,group:'clipboard',order:A});};t('Cut','cut',new n('cut'),1);t('Copy','copy',new n('copy'),4);t('Paste','paste',o,8);a.dialog.add('paste',a.getUrl(this.path+'dialogs/paste.js'));s.on('key',p,s);var u=s.config.forcePasteAsPlainText?'text':'html';s.on('contentDom',function(){var x=s.document.getBody();x.on(u=='text'&&c||b.webkit?'paste':'beforepaste',function(y){if(v)return;q.call(s,y,u,function(z){if(!z)return;var A={};A[u]=z;s.fire('paste',A);});});x.on('beforecut',function(){!v&&r(s);});});if(s.contextMenu){var v;function w(x){c&&(v=1);var y=s.document.$.queryCommandEnabled(x)?2:0;v=0;return y;};s.contextMenu.addListener(function(x,y){var z=y.getCommonAncestor().isReadOnly();return{cut:!z&&w('Cut'),copy:w('Copy'),paste:!z&&(b.webkit?2:w('Paste'))};});}}});})();j.add('colorbutton',{requires:['panelbutton','floatpanel','styles'],init:function(l){var m=l.config,n=l.lang.colorButton,o;if(!b.hc){p('TextColor','fore',n.textColorTitle);p('BGColor','back',n.bgColorTitle);}function p(r,s,t){l.ui.add(r,4,{label:t,title:t,className:'cke_button_'+r.toLowerCase(),modes:{wysiwyg:1},panel:{css:l.skin.editor.css,attributes:{role:'listbox','aria-label':n.panelTitle}},onBlock:function(u,v){v.autoSize=true;v.element.addClass('cke_colorblock');v.element.setHtml(q(u,s));v.element.getDocument().getBody().setStyle('overflow','hidden');var w=v.keys,x=l.lang.dir=='rtl';w[x?37:39]='next';w[40]='next';w[9]='next';w[x?39:37]='prev';w[38]='prev';w[2000+9]='prev';w[32]='click';}});};function q(r,s){var t=[],u=m.colorButton_colors.split(','),v=u.length+(m.colorButton_enableMore?2:1),w=e.addFunction(function(C,D){if(C=='?'){var E=arguments.callee;function F(H){this.removeListener('ok',F);this.removeListener('cancel',F);H.name=='ok'&&E(this.getContentElement('picker','selectedColor').getValue(),D);};l.openDialog('colordialog',function(){this.on('ok',F);this.on('cancel',F);});return;}l.focus();r.hide();l.fire('saveSnapshot');new a.style(m['colorButton_'+D+'Style'],{color:'inherit'}).remove(l.document);if(C){var G=m['colorButton_'+D+'Style'];G.childRule=D=='back'?function(){return false;}:function(H){return H.getName()!='a';};new a.style(G,{color:C}).apply(l.document);}l.fire('saveSnapshot');});t.push('
    ',n.auto,'
    '); +for(var x=0;x');var y=u[x].split('/'),z=y[0],A=y[1]||z;if(!y[1])z='#'+z.replace(/^(.)(.)(.)$/,'$1$1$2$2$3$3');var B=l.lang.colors[A]||A;t.push('');}if(m.colorButton_enableMore)t.push('');t.push('
    ',n.more,'
    ');return t.join('');};}});i.colorButton_enableMore=true;i.colorButton_colors='000,800000,8B4513,2F4F4F,008080,000080,4B0082,696969,B22222,A52A2A,DAA520,006400,40E0D0,0000CD,800080,808080,F00,FF8C00,FFD700,008000,0FF,00F,EE82EE,A9A9A9,FFA07A,FFA500,FFFF00,00FF00,AFEEEE,ADD8E6,DDA0DD,D3D3D3,FFF0F5,FAEBD7,FFFFE0,F0FFF0,F0FFFF,F0F8FF,E6E6FA,FFF';i.colorButton_foreStyle={element:'span',styles:{color:'#(color)'},overrides:[{element:'font',attributes:{color:null}}]};i.colorButton_backStyle={element:'span',styles:{'background-color':'#(color)'}};(function(){j.colordialog={init:function(l){l.addCommand('colordialog',new a.dialogCommand('colordialog'));a.dialog.add('colordialog',this.path+'dialogs/colordialog.js');}};j.add('colordialog',j.colordialog);})();j.add('contextmenu',{requires:['menu'],beforeInit:function(l){l.contextMenu=new j.contextMenu(l);l.addCommand('contextMenu',{exec:function(){l.contextMenu.show(l.document.getBody());}});}});j.contextMenu=e.createClass({$:function(l){this.id='cke_'+e.getNextNumber();this.editor=l;this._.listeners=[];this._.functionId=e.addFunction(function(m){this._.panel.hide();l.focus();l.execCommand(m);},this);this.definition={panel:{className:l.skinClass+' cke_contextmenu',attributes:{'aria-label':l.lang.contextmenu.options}}};},_:{onMenu:function(l,m,n,o){var p=this._.menu,q=this.editor;if(p){p.hide();p.removeAll();}else{p=this._.menu=new a.menu(q,this.definition);p.onClick=e.bind(function(z){p.hide();if(z.onClick)z.onClick();else if(z.command)q.execCommand(z.command);},this);p.onEscape=function(z){var A=this.parent;if(A){A._.panel.hideChild();var B=A._.panel._.panel._.currentBlock,C=B._.focusIndex; +B._.markItem(C);}else if(z==27){this.hide();q.focus();}return false;};}var r=this._.listeners,s=[],t=this.editor.getSelection(),u=t&&t.getStartElement();p.onHide=e.bind(function(){p.onHide=null;if(c){var z=q.getSelection();z&&z.unlock();}this.onHide&&this.onHide();},this);for(var v=0;v ';j.add('elementspath',{requires:['selection'],init:function(n){var o='cke_path_'+n.name,p,q=function(){if(!p)p=a.document.getById(o);return p;},r='cke_elementspath_'+e.getNextNumber()+'_';n._.elementsPath={idBase:r,filters:[]};n.on('themeSpace',function(s){if(s.data.space=='bottom')s.data.html+=''+n.lang.elementsPath.eleLabel+''+'
    '+m+'
    '; +});n.on('selectionChange',function(s){var t=b,u=s.data.selection,v=u.getStartElement(),w=[],x=s.editor,y=x._.elementsPath.list=[],z=x._.elementsPath.filters;while(v){var A=0;for(var B=0;B',D,''+F+'','');}if(D=='body')break;v=v.getParent();}q().setHtml(w.join('')+m);});n.on('contentDomUnload',function(){p&&p.setHtml(m);});n.addCommand('elementsPathFocus',l.toolbarFocus);}});})();a._.elementsPath={click:function(l,m){var n=a.instances[l];n.focus();var o=n._.elementsPath.list[m];n.getSelection().selectElement(o);return false;},keydown:function(l,m,n){var o=k.button._.instances[m],p=a.instances[l],q=p._.elementsPath.idBase,r;n=new d.event(n);var s=p.lang.dir=='rtl';switch(n.getKeystroke()){case s?39:37:case 9:r=a.document.getById(q+(m+1));if(!r)r=a.document.getById(q+'0');r.focus();return false;case s?37:39:case 2000+9:r=a.document.getById(q+(m-1));if(!r)r=a.document.getById(q+(p._.elementsPath.list.length-1));r.focus();return false;case 27:p.focus();return false;case 13:case 32:this.click(l,m);return false;}return true;}};(function(){j.add('enterkey',{requires:['keystrokes','indent'],init:function(s){var t=s.specialKeys;t[13]=q;t[2000+13]=p;}});j.enterkey={enterBlock:function(s,t,u,v){u=u||r(s);if(!u)return;var w=u.document;if(u.checkStartOfBlock()&&u.checkEndOfBlock()){var x=new d.elementPath(u.startContainer),y=x.block;if(y&&(y.is('li')||y.getParent().is('li'))){s.execCommand('outdent');return;}}var z=t==3?'div':'p',A=u.splitBlock(z);if(!A)return;var B=A.previousBlock,C=A.nextBlock,D=A.wasStartOfBlock,E=A.wasEndOfBlock,F;if(C){F=C.getParent();if(F.is('li')){C.breakParent(F);C.move(C.getNext(),true);}}else if(B&&(F=B.getParent())&&F.is('li')){B.breakParent(F);u.moveToElementEditStart(B.getNext()); +B.move(B.getPrevious());}if(!D&&!E){if(C.is('li')&&(F=C.getFirst(d.walker.invisible(true)))&&F.is&&F.is('ul','ol'))(c?w.createText('\xa0'):w.createElement('br')).insertBefore(F);if(C)u.moveToElementEditStart(C);}else{var G;if(B){if(B.is('li')||!o.test(B.getName()))G=B.clone();}else if(C)G=C.clone();if(!G)G=w.createElement(z);else if(v&&!G.is('li'))G.renameNode(z);var H=A.elementPath;if(H)for(var I=0,J=H.elements.length;I0;u--)t[u].deleteContents();return t[0];};})();(function(){var l='nbsp,gt,lt,quot',m='iexcl,cent,pound,curren,yen,brvbar,sect,uml,copy,ordf,laquo,not,shy,reg,macr,deg,plusmn,sup2,sup3,acute,micro,para,middot,cedil,sup1,ordm,raquo,frac14,frac12,frac34,iquest,times,divide,fnof,bull,hellip,prime,Prime,oline,frasl,weierp,image,real,trade,alefsym,larr,uarr,rarr,darr,harr,crarr,lArr,uArr,rArr,dArr,hArr,forall,part,exist,empty,nabla,isin,notin,ni,prod,sum,minus,lowast,radic,prop,infin,ang,and,or,cap,cup,int,there4,sim,cong,asymp,ne,equiv,le,ge,sub,sup,nsub,sube,supe,oplus,otimes,perp,sdot,lceil,rceil,lfloor,rfloor,lang,rang,loz,spades,clubs,hearts,diams,circ,tilde,ensp,emsp,thinsp,zwnj,zwj,lrm,rlm,ndash,mdash,lsquo,rsquo,sbquo,ldquo,rdquo,bdquo,dagger,Dagger,permil,lsaquo,rsaquo,euro',n='Agrave,Aacute,Acirc,Atilde,Auml,Aring,AElig,Ccedil,Egrave,Eacute,Ecirc,Euml,Igrave,Iacute,Icirc,Iuml,ETH,Ntilde,Ograve,Oacute,Ocirc,Otilde,Ouml,Oslash,Ugrave,Uacute,Ucirc,Uuml,Yacute,THORN,szlig,agrave,aacute,acirc,atilde,auml,aring,aelig,ccedil,egrave,eacute,ecirc,euml,igrave,iacute,icirc,iuml,eth,ntilde,ograve,oacute,ocirc,otilde,ouml,oslash,ugrave,uacute,ucirc,uuml,yacute,thorn,yuml,OElig,oelig,Scaron,scaron,Yuml',o='Alpha,Beta,Gamma,Delta,Epsilon,Zeta,Eta,Theta,Iota,Kappa,Lambda,Mu,Nu,Xi,Omicron,Pi,Rho,Sigma,Tau,Upsilon,Phi,Chi,Psi,Omega,alpha,beta,gamma,delta,epsilon,zeta,eta,theta,iota,kappa,lambda,mu,nu,xi,omicron,pi,rho,sigmaf,sigma,tau,upsilon,phi,chi,psi,omega,thetasym,upsih,piv'; +function p(q,r){var s={},t=[],u={nbsp:'\xa0',shy:'­',gt:'>',lt:'<'};q=q.replace(/\b(nbsp|shy|gt|lt|amp)(?:,|$)/g,function(z,A){var B=r?'&'+A+';':u[A],C=r?u[A]:'&'+A+';';s[B]=C;t.push(B);return '';});if(!r){q=q.split(',');var v=document.createElement('div'),w;v.innerHTML='&'+q.join(';&')+';';w=v.innerHTML;v=null;for(var x=0;x'+t+'',t);}},onClick:function(s){l.focus();l.fire('saveSnapshot');p[s].apply(l.document);setTimeout(function(){l.fire('saveSnapshot');},0);},onRender:function(){l.on('selectionChange',function(s){var t=this.getValue(),u=s.data.path;for(var v in p){if(p[v].checkActive(u)){if(v!=t)this.setValue(v,l.lang.format['tag_'+v]);return;}}this.setValue('');},this);}});}});i.format_tags='p;h1;h2;h3;h4;h5;h6;pre;address;div';i.format_p={element:'p'};i.format_div={element:'div'};i.format_pre={element:'pre'};i.format_address={element:'address'};i.format_h1={element:'h1'};i.format_h2={element:'h2'};i.format_h3={element:'h3'};i.format_h4={element:'h4'};i.format_h5={element:'h5'};i.format_h6={element:'h6'};j.add('forms',{init:function(l){var m=l.lang;l.addCss('form{border: 1px dotted #FF0000;padding: 2px;}\n');l.addCss('img.cke_hidden{background-image: url('+a.getUrl(this.path+'images/hiddenfield.gif')+');'+'background-position: center center;'+'background-repeat: no-repeat;'+'border: 1px solid #a9a9a9;'+'width: 16px !important;'+'height: 16px !important;'+'}'); +var n=function(p,q,r){l.addCommand(q,new a.dialogCommand(q));l.ui.addButton(p,{label:m.common[p.charAt(0).toLowerCase()+p.slice(1)],command:q});a.dialog.add(q,r);},o=this.path+'dialogs/';n('Form','form',o+'form.js');n('Checkbox','checkbox',o+'checkbox.js');n('Radio','radio',o+'radio.js');n('TextField','textfield',o+'textfield.js');n('Textarea','textarea',o+'textarea.js');n('Select','select',o+'select.js');n('Button','button',o+'button.js');n('ImageButton','imagebutton',j.getPath('image')+'dialogs/image.js');n('HiddenField','hiddenfield',o+'hiddenfield.js');if(l.addMenuItems)l.addMenuItems({form:{label:m.form.menu,command:'form',group:'form'},checkbox:{label:m.checkboxAndRadio.checkboxTitle,command:'checkbox',group:'checkbox'},radio:{label:m.checkboxAndRadio.radioTitle,command:'radio',group:'radio'},textfield:{label:m.textfield.title,command:'textfield',group:'textfield'},hiddenfield:{label:m.hidden.title,command:'hiddenfield',group:'hiddenfield'},imagebutton:{label:m.image.titleButton,command:'imagebutton',group:'imagebutton'},button:{label:m.button.title,command:'button',group:'button'},select:{label:m.select.title,command:'select',group:'select'},textarea:{label:m.textarea.title,command:'textarea',group:'textarea'}});if(l.contextMenu){l.contextMenu.addListener(function(p){if(p&&p.hasAscendant('form',true)&&!p.isReadOnly())return{form:2};});l.contextMenu.addListener(function(p){if(p&&!p.isReadOnly()){var q=p.getName();if(q=='select')return{select:2};if(q=='textarea')return{textarea:2};if(q=='input'){var r=p.getAttribute('type');if(r=='text'||r=='password')return{textfield:2};if(r=='button'||r=='submit'||r=='reset')return{button:2};if(r=='checkbox')return{checkbox:2};if(r=='radio')return{radio:2};if(r=='image')return{imagebutton:2};}if(q=='img'&&p.getAttribute('_cke_real_element_type')=='hiddenfield')return{hiddenfield:2};}});}l.on('doubleclick',function(p){var q=p.data.element;if(q.is('form'))p.data.dialog='form';else if(q.is('select'))p.data.dialog='select';else if(q.is('textarea'))p.data.dialog='textarea';else if(q.is('img')&&q.getAttribute('_cke_real_element_type')=='hiddenfield')p.data.dialog='hiddenfield';else if(q.is('input')){var r=q.getAttribute('type');switch(r){case 'text':case 'password':p.data.dialog='textfield';break;case 'button':case 'submit':case 'reset':p.data.dialog='button';break;case 'checkbox':p.data.dialog='checkbox';break;case 'radio':p.data.dialog='radio';break;case 'image':p.data.dialog='imagebutton';break;}}});},afterInit:function(l){var m=l.dataProcessor,n=m&&m.htmlFilter,o=m&&m.dataFilter; +if(c)n&&n.addRules({elements:{input:function(p){var q=p.attributes,r=q.type;if(r=='checkbox'||r=='radio')q.value=='on'&&delete q.value;}}});if(o)o.addRules({elements:{input:function(p){if(p.attributes.type=='hidden')return l.createFakeParserElement(p,'cke_hidden','hiddenfield');}}});},requires:['image','fakeobjects']});if(c)h.prototype.hasAttribute=function(l){var o=this;var m=o.$.attributes.getNamedItem(l);if(o.getName()=='input')switch(l){case 'class':return o.$.className.length>0;case 'checked':return!!o.$.checked;case 'value':var n=o.getAttribute('type');if(n=='checkbox'||n=='radio')return o.$.value!='on';break;default:}return!!(m&&m.specified);};(function(){var l={canUndo:false,exec:function(n){n.insertElement(n.document.createElement('hr'));}},m='horizontalrule';j.add(m,{init:function(n){n.addCommand(m,l);n.ui.addButton('HorizontalRule',{label:n.lang.horizontalrule,command:m});}});})();(function(){var l=/^[\t\r\n ]*(?: |\xa0)$/,m='{cke_protected}';function n(R){var S=R.children.length,T=R.children[S-1];while(T&&T.type==3&&!e.trim(T.value))T=R.children[--S];return T;};function o(R,S){var T=R.children,U=n(R);if(U){if((S||!c)&&U.type==1&&U.name=='br')T.pop();if(U.type==3&&l.test(U.value))T.pop();}};function p(R){var S=n(R);return!S||S.type==1&&S.name=='br'||R.name=='form'&&S.name=='input';};function q(R){o(R,true);if(p(R))if(c)R.add(new a.htmlParser.text('\xa0'));else R.add(new a.htmlParser.element('br',{}));};function r(R){o(R);if(p(R))R.add(new a.htmlParser.text('\xa0'));};var s=f,t=e.extend({},s.$block,s.$listItem,s.$tableContent);for(var u in t){if(!('br' in s[u]))delete t[u];}delete t.pre;var v={elements:{},attributeNames:[[/^on/,'_cke_pa_on']]},w={elements:{}};for(u in t)w.elements[u]=q;var x={elementNames:[[/^cke:/,''],[/^\?xml:namespace$/,'']],attributeNames:[[/^_cke_(saved|pa)_/,''],[/^_cke.*/,''],['hidefocus','']],elements:{$:function(R){var S=R.attributes;if(S){if(S.cke_temp)return false;var T=['name','href','src'],U;for(var V=0;V]+)))([^>]*)>/gi,C=/\s_cke_saved_src\s*=/,D=/(?:])[^>]*>[\s\S]*<\/style>)|(?:<(:?link|meta|base)[^>]*>)/gi,E=/([^<]*)<\/cke:encoded>/gi,F=/(<\/?)((?:object|embed|param|html|body|head|title)[^>]*>)/gi,G=/(<\/?)cke:((?:html|body|head|title)[^>]*>)/gi,H=/]*?)\/?>(?!\s*<\/cke:\1)/gi;function I(R){return R.replace(B,function(S,T,U,V,W){if(V=='src'&&C.test(S))return S;else return '<'+T+U+' _cke_saved_'+U+W+'>';});};function J(R){return R.replace(D,function(S){return ''+encodeURIComponent(S)+'';});};function K(R){return R.replace(E,function(S,T){return decodeURIComponent(T);});};function L(R){return R.replace(F,'$1cke:$2');};function M(R){return R.replace(G,'$1$2');};function N(R){return R.replace(H,'');};function O(R){return R.replace(//g,function(S){return '';});};function P(R){return R.replace(//g,function(S,T){return decodeURIComponent(T);});};function Q(R,S){var T=[],U=/<\!--\{cke_temp(comment)?\}(\d*?)-->/g,V=[//gi,//gi].concat(S);R=R.replace(//g,function(X){return '';});for(var W=0;W';});R=R.replace(U,function(X,Y,Z){return ''; +});return R;};j.add('htmldataprocessor',{requires:['htmlwriter'],init:function(R){var S=R.dataProcessor=new a.htmlDataProcessor(R);S.writer.forceSimpleAmpersand=R.config.forceSimpleAmpersand;S.dataFilter.addRules(v);S.dataFilter.addRules(w);S.htmlFilter.addRules(x);S.htmlFilter.addRules(y);}});a.htmlDataProcessor=function(R){var S=this;S.editor=R;S.writer=new a.htmlWriter();S.dataFilter=new a.htmlParser.filter();S.htmlFilter=new a.htmlParser.filter();};a.htmlDataProcessor.prototype={toHtml:function(R,S){R=Q(R,this.editor.config.protectedSource);R=I(R);R=J(R);R=L(R);R=N(R);var T=new h('div');T.setHtml('a'+R);R=T.getHtml().substr(1);R=M(R);R=K(R);R=P(R);var U=a.htmlParser.fragment.fromHtml(R,S),V=new a.htmlParser.basicWriter();U.writeHtml(V,this.dataFilter);R=V.getHtml(true);R=O(R);return R;},toDataFormat:function(R,S){var T=this.writer,U=a.htmlParser.fragment.fromHtml(R,S);T.reset();U.writeHtml(T,this.htmlFilter);return T.getHtml(true);}};})();i.forceSimpleAmpersand=false;j.add('image',{init:function(l){var m='image';a.dialog.add(m,this.path+'dialogs/image.js');l.addCommand(m,new a.dialogCommand(m));l.ui.addButton('Image',{label:l.lang.common.image,command:m});l.on('doubleclick',function(n){var o=n.data.element;if(o.is('img')&&!o.getAttribute('_cke_realelement'))n.data.dialog='image';});if(l.addMenuItems)l.addMenuItems({image:{label:l.lang.image.menu,command:'image',group:'image'}});if(l.contextMenu)l.contextMenu.addListener(function(n,o){if(!n||!n.is('img')||n.getAttribute('_cke_realelement')||n.isReadOnly())return null;return{image:2};});}});i.image_removeLinkByEmptyURL=true;(function(){var l={ol:1,ul:1},m=d.walker.whitespaces(true),n=d.walker.bookmark(false,true);function o(t,u){t.getCommand(this.name).setState(u);};function p(t){var C=this;var u=t.editor,v=t.data.path,w=v&&v.contains(l);if(w)return o.call(C,u,2);if(!C.useIndentClasses&&C.name=='indent')return o.call(C,u,2);var x=t.data.path,y=x.block||x.blockLimit;if(!y)return o.call(C,u,0);if(C.useIndentClasses){var z=y.$.className.match(C.classNameRegex),A=0;if(z){z=z[1];A=C.indentClassMap[z];}if(C.name=='outdent'&&!A||C.name=='indent'&&A==u.config.indentClasses.length)return o.call(C,u,0);return o.call(C,u,2);}else{var B=parseInt(y.getStyle(r(y)),10);if(isNaN(B))B=0;if(B<=0)return o.call(C,u,0);return o.call(C,u,2);}};function q(t,u){var w=this;w.name=u;w.useIndentClasses=t.config.indentClasses&&t.config.indentClasses.length>0;if(w.useIndentClasses){w.classNameRegex=new RegExp('(?:^|\\s+)('+t.config.indentClasses.join('|')+')(?=$|\\s)'); +w.indentClassMap={};for(var v=0;vZ;U++)Y[U].indent+=V;var ab=N.getAttribute('dir')||N.getStyle('direction'),ac=j.list.arrayToList(Y,v,null,t.config.enterMode,ab);if(u.name=='outdent'){var ad;if((ad=N.getParent())&&ad.is('li')){var ae=ac.listNode.getChildren(),af=[],ag=ae.count(),ah;for(U=ag-1;U>=0;U--){if((ah=ae.getItem(U))&&ah.is&&ah.is('li'))af.push(ah);}}}if(ac)ac.listNode.replace(N);if(af&&af.length)for(U=0;U=0;y--){v=t[y].createIterator();v.enlargeBr=r!=2;while(w=v.getNextParagraph()){w.removeAttribute('align');w.removeStyle('text-align');var z=u&&(w.$.className=e.ltrim(w.$.className.replace(B.cssClassRegex,''))),A=B.state==2&&(!x||m(w,true)!=B.value);if(u){if(A)w.addClass(u);else if(!z)w.removeAttribute('class');}else if(A)w.setStyle('text-align',B.value);}}p.focus();p.forceNextSelectionCheck();q.selectBookmarks(s);}};j.add('justify',{init:function(p){var q=new o(p,'justifyleft','left'),r=new o(p,'justifycenter','center'),s=new o(p,'justifyright','right'),t=new o(p,'justifyblock','justify');p.addCommand('justifyleft',q);p.addCommand('justifycenter',r);p.addCommand('justifyright',s);p.addCommand('justifyblock',t);p.ui.addButton('JustifyLeft',{label:p.lang.justify.left,command:'justifyleft'});p.ui.addButton('JustifyCenter',{label:p.lang.justify.center,command:'justifycenter'});p.ui.addButton('JustifyRight',{label:p.lang.justify.right,command:'justifyright'});p.ui.addButton('JustifyBlock',{label:p.lang.justify.block,command:'justifyblock'});p.on('selectionChange',e.bind(n,q));p.on('selectionChange',e.bind(n,s));p.on('selectionChange',e.bind(n,r));p.on('selectionChange',e.bind(n,t));},requires:['domiterator']});})();e.extend(i,{justifyClasses:null});j.add('keystrokes',{beforeInit:function(l){l.keystrokeHandler=new a.keystrokeHandler(l);l.specialKeys={};},init:function(l){var m=l.config.keystrokes,n=l.config.blockedKeystrokes,o=l.keystrokeHandler.keystrokes,p=l.keystrokeHandler.blockedKeystrokes;for(var q=0;qE[G-1].indent+1){var K=E[G-1].indent+1-E[G].indent,L=E[G].indent;while(E[G]&&E[G].indent>=L){E[G].indent+=K;G++;}G--;}}var M=j.list.arrayToList(E,D,null,B.config.enterMode,C.root.getAttribute('dir')),N=M.listNode,O,P;function Q(R){if((O=N[R?'getFirst':'getLast']())&&!(O.is&&O.isBlockBoundary())&&(P=C.root[R?'getPrevious':'getNext'](d.walker.whitespaces(true)))&&!(P.is&&P.isBlockBoundary({br:1})))B.document.createElement('br')[R?'insertBefore':'insertAfter'](O); +};Q(true);Q();N.replace(C.root);};function t(B,C){this.name=B;this.type=C;};t.prototype={exec:function(B){B.focus();var C=B.document,D=B.getSelection(),E=D&&D.getRanges(true);if(!E||E.length<1)return;if(this.state==2){var F=C.getBody();F.trim();if(!F.getFirst()){var G=C.createElement(B.config.enterMode==1?'p':B.config.enterMode==3?'div':'br');G.appendTo(F);E=new d.rangeList([new d.range(C)]);if(G.is('br')){E[0].setStartBefore(G);E[0].setEndAfter(G);}else E[0].selectNodeContents(G);D.selectRanges(E);}else{var H=E.length==1&&E[0],I=H&&H.getEnclosedNode();if(I&&I.is&&this.type==I.getName())n.call(this,B,1);}}var J=D.createBookmarks(true),K=[],L={},M=E.createIterator(),N=0;while((H=M.getNextRange())&&++N){var O=H.getBoundaryNodes(),P=O.startNode,Q=O.endNode;if(P.type==1&&P.getName()=='td')H.setStartAt(O.startNode,1);if(Q.type==1&&Q.getName()=='td')H.setEndAt(O.endNode,2);var R=H.createIterator(),S;R.forceBrBreak=this.state==2;while(S=R.getNextParagraph()){if(S.getCustomData('list_block'))continue;else h.setMarker(L,S,'list_block',1);var T=new d.elementPath(S),U=T.elements,V=U.length,W=null,X=false,Y=T.blockLimit,Z;for(var aa=V-1;aa>=0&&(Z=U[aa]);aa--){if(l[Z.getName()]&&Y.contains(Z)){Y.removeCustomData('list_group_object_'+N);var ab=Z.getCustomData('list_group_object');if(ab)ab.contents.push(S);else{ab={root:Z,contents:[S]};K.push(ab);h.setMarker(L,Z,'list_group_object',ab);}X=true;break;}}if(X)continue;var ac=Y;if(ac.getCustomData('list_group_object_'+N))ac.getCustomData('list_group_object_'+N).contents.push(S);else{ab={root:ac,contents:[S]};h.setMarker(L,ac,'list_group_object_'+N,ab);K.push(ab);}}}var ad=[];while(K.length>0){ab=K.shift();if(this.state==2){if(l[ab.root.getName()])p.call(this,B,ab,L,ad);else r.call(this,B,ab,ad);}else if(this.state==1&&l[ab.root.getName()])s.call(this,B,ab,L);}for(aa=0;aa0)for(var t=s.length-1;t>=0;t--){var u=s[t][0],v=s[t][1];if(v)u.insertBefore(v);else u.appendTo(r);}};function n(r,s){var t=l(r),u={},v=r.$;if(!s){u['class']=v.className||'';v.className='';}u.inline=v.style.cssText||'';if(!s)v.style.cssText='position: static; overflow: visible';m(t);return u;};function o(r,s){var t=l(r),u=r.$;if('class' in s)u.className=s['class'];if('inline' in s)u.style.cssText=s.inline;m(t);};function p(r){var s=a.instances;for(var t in s){var u=s[t];if(u.mode=='wysiwyg'){var v=u.document.getBody();v.setAttribute('contentEditable',false);v.setAttribute('contentEditable',true);}}if(r.focusManager.hasFocus){r.toolbox.focus(); +r.focus();}};function q(r){if(!c||b.version>6)return null;var s=h.createFromHtml('');return r.append(s,true);};j.add('maximize',{init:function(r){var s=r.lang,t=a.document,u=t.getWindow(),v,w,x,y;function z(){var B=u.getViewPaneSize();y&&y.setStyles({width:B.width+'px',height:B.height+'px'});r.resize(B.width,B.height,null,true);};var A=2;r.addCommand('maximize',{modes:{wysiwyg:1,source:1},editorFocus:false,exec:function(){var B=r.container.getChild(1),C=r.getThemeSpace('contents');if(r.mode=='wysiwyg'){var D=r.getSelection();v=D&&D.getRanges();w=u.getScrollPosition();}else{var E=r.textarea.$;v=!c&&[E.selectionStart,E.selectionEnd];w=[E.scrollLeft,E.scrollTop];}if(this.state==2){u.on('resize',z);x=u.getScrollPosition();var F=r.container;while(F=F.getParent()){F.setCustomData('maximize_saved_styles',n(F));F.setStyle('z-index',r.config.baseFloatZIndex-1);}C.setCustomData('maximize_saved_styles',n(C,true));B.setCustomData('maximize_saved_styles',n(B,true));if(c)t.$.documentElement.style.overflow=t.getBody().$.style.overflow='hidden';else t.getBody().setStyles({overflow:'hidden',width:'0px',height:'0px'});c?setTimeout(function(){u.$.scrollTo(0,0);},0):u.$.scrollTo(0,0);var G=u.getViewPaneSize();B.setStyle('position','absolute');B.$.offsetLeft;B.setStyles({'z-index':r.config.baseFloatZIndex-1,left:'0px',top:'0px'});y=q(B);B.addClass('cke_maximized');z();var H=B.getDocumentPosition();B.setStyles({left:-1*H.x+'px',top:-1*H.y+'px'});b.gecko&&p(r);}else if(this.state==1){u.removeListener('resize',z);var I=[C,B];for(var J=0;J ');n=l.createFakeElement(n,'cke_pagebreak','div');n.setAttribute('alt',m);n.setAttribute('aria-label',m);var o=l.getSelection().getRanges(true);l.fire('saveSnapshot');for(var p,q=o.length-1;q>=0;q--){p=o[q];if(q1&&m.substr(m.length-1,1)=='%')m=parseInt(window.screen.width*parseInt(m,10)/100,10);if(typeof n=='string'&&n.length>1&&n.substr(n.length-1,1)=='%')n=parseInt(window.screen.height*parseInt(n,10)/100,10);if(m<640)m=640;if(n<420)n=420;var p=parseInt((window.screen.height-n)/2,10),q=parseInt((window.screen.width-m)/2,10);o=(o||'location=no,menubar=no,toolbar=no,dependent=yes,minimizable=no,modal=yes,alwaysRaised=yes,resizable=yes,scrollbars=yes')+',width='+m+',height='+n+',top='+p+',left='+q; +var r=window.open('',null,o,true);if(!r)return false;try{r.moveTo(q,p);r.resizeTo(m,n);r.focus();r.location.href=l;}catch(s){r=window.open(l,null,o,true);}return true;}});(function(){var l={modes:{wysiwyg:1,source:1},canUndo:false,exec:function(n){var o,p=n.config,q=p.baseHref?'':'',r=b.isCustomDomain();if(p.fullPage)o=n.getData().replace(//,'$&'+q).replace(/[^>]*(?=<\/title>)/,n.lang.preview);else{var s=''+''+q+''+n.lang.preview+''+e.buildStyleHtml(n.config.contentsCss)+''+s+n.getData()+'';}var u=640,v=420,w=80;try{var x=window.screen;u=Math.round(x.width*0.8);v=Math.round(x.height*0.7);w=Math.round(x.width*0.1);}catch(A){}var y='';if(r){window._cke_htmlToLoad=o;y='javascript:void( (function(){document.open();document.domain="'+document.domain+'";'+'document.write( window.opener._cke_htmlToLoad );'+'document.close();'+'window.opener._cke_htmlToLoad = null;'+'})() )';}var z=window.open(y,null,'toolbar=yes,location=no,status=yes,menubar=yes,scrollbars=yes,resizable=yes,width='+u+',height='+v+',left='+w);if(!r){z.document.open();z.document.write(o);z.document.close();}}},m='preview';j.add(m,{init:function(n){n.addCommand(m,l);n.ui.addButton('Preview',{label:n.lang.preview,command:m});}});})();j.add('print',{init:function(l){var m='print',n=l.addCommand(m,j.print);l.ui.addButton('Print',{label:l.lang.print,command:m});}});j.print={exec:function(l){if(b.opera)return;else if(b.gecko)l.window.$.print();else l.document.$.execCommand('Print');},canUndo:false,modes:{wysiwyg:!b.opera}};j.add('removeformat',{requires:['selection'],init:function(l){l.addCommand('removeFormat',j.removeformat.commands.removeformat);l.ui.addButton('RemoveFormat',{label:l.lang.removeFormat,command:'removeFormat'});l._.removeFormat={filters:[]};}});j.removeformat={commands:{removeformat:{exec:function(l){var m=l._.removeFormatRegex||(l._.removeFormatRegex=new RegExp('^(?:'+l.config.removeFormatTags.replace(/,/g,'|')+')$','i')),n=l._.removeAttributes||(l._.removeAttributes=l.config.removeFormatAttributes.split(',')),o=j.removeformat.filter,p=l.getSelection().getRanges(true),q=p.createIterator(),r;while(r=q.getNextRange()){if(r.collapsed)continue;r.enlarge(1);var s=r.createBookmark(),t=s.startNode,u=s.endNode,v=function(y){var z=new d.elementPath(y),A=z.elements; +for(var B=1,C;C=A[B];B++){if(C.equals(z.block)||C.equals(z.blockLimit))break;if(m.test(C.getName())&&o(l,C))y.breakParent(C);}};v(t);v(u);var w=t.getNextSourceNode(true,1);while(w){if(w.equals(u))break;var x=w.getNextSourceNode(false,1);if(!(w.getName()=='img'&&w.getAttribute('_cke_realelement'))&&o(l,w))if(m.test(w.getName()))w.remove(true);else{w.removeAttributes(n);l.fire('removeFormatCleanup',w);}w=x;}r.moveToBookmark(s);}l.getSelection().selectRanges(p);}}},filter:function(l,m){var n=l._.removeFormat.filters;for(var o=0;op.width&&(m.resize_minWidth=p.width);m.resize_minHeight>p.height&&(m.resize_minHeight=p.height);a.document.on('mousemove',s);a.document.on('mouseup',t);if(l.document){l.document.on('mousemove',s);l.document.on('mouseup',t);}});l.on('destroy',function(){e.removeFunction(u);});l.on('themeSpace',function(v){if(v.data.space=='bottom'){var w='';if(q&&!r)w=' cke_resizer_horizontal';if(!q&&r)w=' cke_resizer_vertical';v.data.html+='
    '; +}},l,null,100);}}});(function(){var l={modes:{wysiwyg:1,source:1},exec:function(n){var o=n.element.$.form;if(o)try{o.submit();}catch(p){if(o.submit.click)o.submit.click();}}},m='save';j.add(m,{init:function(n){var o=n.addCommand(m,l);o.modes={wysiwyg:!!n.element.$.form};n.ui.addButton('Save',{label:n.lang.save,command:m});}});})();(function(){var l='scaytcheck',m='';function n(s,t){var u=false,v;for(v in t){if(t[v]===s||t[v]==s){u=true;break;}}return u;};var o=function(){var s=this,t=function(){var x={};x.srcNodeRef=s.document.getWindow().$.frameElement;x.assocApp='CKEDITOR.'+a.version+'@'+a.revision;x.customerid=s.config.scayt_customerid||'1:WvF0D4-UtPqN1-43nkD4-NKvUm2-daQqk3-LmNiI-z7Ysb4-mwry24-T8YrS3-Q2tpq2';x.customDictionaryIds=s.config.scayt_customDictionaryIds||'';x.userDictionaryName=s.config.scayt_userDictionaryName||'';x.sLang=s.config.scayt_sLang||'en_US';x.onLoad=function(){if(!(c&&b.version<8))this.addStyle(this.selectorCss(),'padding-bottom: 2px !important;');if(s.focusManager.hasFocus&&!p.isControlRestored(s))this.focus();};x.onBeforeChange=function(){if(p.getScayt(s)&&!s.checkDirty())setTimeout(function(){s.resetDirty();},0);};var y=window.scayt_custom_params;if(typeof y=='object')for(var z in y)x[z]=y[z];if(p.getControlId(s))x.id=p.getControlId(s);var A=new window.scayt(x);A.afterMarkupRemove.push(function(H){new h(H,A.document).mergeSiblings();});var B=p.instances[s.name];if(B){A.sLang=B.sLang;A.option(B.option());A.paused=B.paused;}p.instances[s.name]=A;var C='scaytButton',D=window.scayt.uiTags,E=[];for(var F=0,G=4;F=0){this.setState(0);p.loadEngine(s);}}};j.add('scayt',{requires:['menubutton'],beforeInit:function(s){var t=s.config.scayt_contextMenuItemsOrder||'suggest|moresuggest|control',u='';t=t.split('|');if(t&&t.length)for(var v in t)u+='scayt_'+t[v]+(t.length!=parseInt(v,10)+1?',':'');s.config.menu_groups=u+','+s.config.menu_groups;},init:function(s){var t={},u={},v=s.addCommand(l,r);a.dialog.add(l,a.getUrl(this.path+'dialogs/options.js'));var w=s.config.scayt_uiTabs||'1,1,1',x=[];w=w.split(',');for(var y=0,z=3;y tr > td, .%1 table.%2 > tr > th,','.%1 table.%2 > tbody > tr > td, .%1 table.%2 > tbody > tr > th,','.%1 table.%2 > thead > tr > td, .%1 table.%2 > thead > tr > th,','.%1 table.%2 > tfoot > tr > td, .%1 table.%2 > tfoot > tr > th','{','border : #d3d3d3 1px dotted','}']).join('');m=n.replace(/%2/g,l).replace(/%1/g,'cke_show_borders ');var o={preserveState:true,editorFocus:false,exec:function(p){this.toggleState();this.refresh(p);},refresh:function(p){var q=this.state==1?'addClass':'removeClass'; +p.document.getBody()[q]('cke_show_borders');}};j.add('showborders',{requires:['wysiwygarea'],modes:{wysiwyg:1},init:function(p){var q=p.addCommand('showborders',o);q.canUndo=false;if(p.config.startupShowBorders!==false)q.setState(1);p.addCss(m);p.on('mode',function(){if(q.state!=0)q.refresh(p);},null,null,100);p.on('contentDom',function(){if(q.state!=0)q.refresh(p);});p.on('removeFormatCleanup',function(r){var s=r.data;if(p.getCommand('showborders').state==1&&s.is('table')&&(!s.hasAttribute('border')||parseInt(s.getAttribute('border'),10)<=0))s.addClass(l);});},afterInit:function(p){var q=p.dataProcessor,r=q&&q.dataFilter,s=q&&q.htmlFilter;if(r)r.addRules({elements:{table:function(t){var u=t.attributes,v=u['class'],w=parseInt(u.border,10);if(!w||w<=0)u['class']=(v||'')+' '+l;}}});if(s)s.addRules({elements:{table:function(t){var u=t.attributes,v=u['class'];v&&(u['class']=v.replace(l,'').replace(/\s{2}/,' ').replace(/^\s+|\s+$/,''));}}});}});a.on('dialogDefinition',function(p){var q=p.data.name;if(q=='table'||q=='tableProperties'){var r=p.data.definition,s=r.getContents('info'),t=s.get('txtBorder'),u=t.commit;t.commit=e.override(u,function(x){return function(y,z){x.apply(this,arguments);var A=parseInt(this.getValue(),10);z[!A||A<=0?'addClass':'removeClass'](l);};});var v=r.getContents('advanced'),w=v&&v.get('advCSSClasses');if(w){w.setup=e.override(w.setup,function(x){return function(){x.apply(this,arguments);this.setValue(this.getValue().replace(/cke_show_border/,''));};});w.commit=e.override(w.commit,function(x){return function(y,z){x.apply(this,arguments);if(!parseInt(z.getAttribute('border'),10))z.addClass('cke_show_border');};});}}});})();j.add('sourcearea',{requires:['editingblock'],init:function(l){var m=j.sourcearea,n=a.document.getWindow();l.on('editingBlockReady',function(){var o,p;l.addMode('source',{load:function(q,r){if(c&&b.version<8)q.setStyle('position','relative');l.textarea=o=new h('textarea');o.setAttributes({dir:'ltr',tabIndex:b.webkit?-1:l.tabIndex,role:'textbox','aria-label':l.lang.editorTitle.replace('%1',l.name)});o.addClass('cke_source');o.addClass('cke_enable_context_menu');var s={width:b.ie7Compat?'99%':'100%',height:'100%',resize:'none',outline:'none','text-align':'left'};if(c){p=function(){o.hide();o.setStyle('height',q.$.clientHeight+'px');o.setStyle('width',q.$.clientWidth+'px');o.show();};l.on('resize',p);n.on('resize',p);setTimeout(p,0);}else o.on('mousedown',function(u){u.data.stopPropagation();});q.setHtml('');q.append(o);o.setStyles(s); +l.fire('ariaWidget',o);o.on('blur',function(){l.focusManager.blur();});o.on('focus',function(){l.focusManager.focus();});l.mayBeDirty=true;this.loadData(r);var t=l.keystrokeHandler;if(t)t.attach(o);setTimeout(function(){l.mode='source';l.fire('mode');},b.gecko||b.webkit?100:0);},loadData:function(q){o.setValue(q);l.fire('dataReady');},getData:function(){return o.getValue();},getSnapshotData:function(){return o.getValue();},unload:function(q){o.clearCustomData();l.textarea=o=null;if(p){l.removeListener('resize',p);n.removeListener('resize',p);}if(c&&b.version<8)q.removeStyle('position');},focus:function(){o.focus();}});});l.addCommand('source',m.commands.source);if(l.ui.addButton)l.ui.addButton('Source',{label:l.lang.source,command:'source'});l.on('mode',function(){l.getCommand('source').setState(l.mode=='source'?1:2);});}});j.sourcearea={commands:{source:{modes:{wysiwyg:1,source:1},editorFocus:false,exec:function(l){if(l.mode=='wysiwyg')l.fire('saveSnapshot');l.getCommand('source').setState(0);l.setMode(l.mode=='source'?'wysiwyg':'source');},canUndo:false}}};(function(){j.add('stylescombo',{requires:['richcombo','styles'],init:function(m){var n=m.config,o=m.lang.stylesCombo,p={},q=[];function r(s){m.getStylesSet(function(t){if(!q.length){var u,v;for(var w=0;w0)return;if(S.type==1&&m.test(S.getName())&&!S.getCustomData('selected_cell')){h.setMarker(J,S,'selected_cell',true);I.push(S);}};for(var L=0;L0&&P.$.rows[K]||P.$.parentNode);for(M=I.length;M>=0;M--){if(I[M])r(I[M]);}return J;}else if(F instanceof h){P=F.getAscendant('table');if(P.$.rows.length==1)P.remove();else F.remove();}return 0;};function s(F,G){var H=F.getStartElement(),I=H.getAscendant('td',true)||H.getAscendant('th',true);if(!I)return;var J=I.getAscendant('table'),K=I.$.cellIndex;for(var L=0;L1){K=G[I-1]+1;break;}}if(!K)K=G[0]>0?G[0]-1:G[G.length-1]+1;var M=H.$.rows;for(I=0,J=M.length;I=0;I--){if(G[I])u(G[I]);}return H;}else if(F instanceof h){var J=F.getAscendant('table');if(!J)return null;var K=F.$.cellIndex;for(I=J.$.rows.length-1;I>=0;I--){var L=new h(J.$.rows[I]);if(!K&&L.$.cells.length==1){r(L);continue;}if(L.$.cells[K])L.$.removeChild(L.$.cells[K]);}}return null;};function v(F,G){var H=F.getStartElement(),I=H.getAscendant('td',true)||H.getAscendant('th',true);if(!I)return;var J=I.clone();if(!c)J.appendBogus();if(G)J.insertBefore(I);else J.insertAfter(I);};function w(F){if(F instanceof d.selection){var G=n(F),H=G[0]&&G[0].getAscendant('table'),I=o(G);for(var J=G.length-1;J>=0;J--)w(G[J]);if(I)y(I,true);else if(H)H.remove();}else if(F instanceof h){var K=F.getParent();if(K.getChildCount()==1)K.remove();else F.remove();}};function x(F){var G=F.getBogus();G&&G.remove();F.trim();};function y(F,G){var H=new d.range(F.getDocument());if(!H['moveToElementEdit'+(G?'End':'Start')](F)){H.selectNodeContents(F);H.collapse(G?false:true);}H.select(true);};function z(F,G,H){var I=F[G];if(typeof H=='undefined')return I;for(var J=0;I&&J=P)L.removeAttribute('rowSpan');else L.$.rowSpan=V;if(V>=O)L.removeAttribute('colSpan');else L.$.colSpan=W;var ah=new d.nodeList(M.$.rows),ai=ah.count();for(Z=ai-1;Z>=0;Z--){var aj=ah.getItem(Z);if(!aj.$.cells.length){aj.remove();ai++;continue;}}return L;}else return V*W==Y;};function C(F,G){var H=n(F);if(H.length>1)return false;else if(G)return true;var I=H[0],J=I.getParent(),K=J.getAscendant('table'),L=e.buildTableMap(K),M=J.$.rowIndex,N=z(L,M,I),O=I.$.rowSpan,P,Q,R,S;if(O>1){Q=Math.ceil(O/2);R=Math.floor(O/2);S=M+Q;var T=new h(K.$.rows[S]),U=z(L,S),V;P=I.clone();for(var W=0;WN){P.insertBefore(new h(V));break;}else V=null;}if(!V)T.append(P,true);}else{R=Q=1;T=J.clone();T.insertAfter(J);T.append(P=I.clone());var X=z(L,M);for(var Y=0;Y1)return false;else if(G)return true;var I=H[0],J=I.getParent(),K=J.getAscendant('table'),L=e.buildTableMap(K),M=J.$.rowIndex,N=z(L,M,I),O=I.$.colSpan,P,Q,R;if(O>1){Q=Math.ceil(O/2);R=Math.floor(O/2);}else{R=Q=1;var S=A(L,N);for(var T=0;T0?2:0};}},tablecell_insertBefore:{label:G.cell.insertBefore,group:'tablecell',command:'cellInsertBefore',order:5},tablecell_insertAfter:{label:G.cell.insertAfter,group:'tablecell',command:'cellInsertAfter',order:10},tablecell_delete:{label:G.cell.deleteCell,group:'tablecell',command:'cellDelete',order:15},tablecell_merge:{label:G.cell.merge,group:'tablecell',command:'cellMerge',order:16},tablecell_merge_right:{label:G.cell.mergeRight,group:'tablecell',command:'cellMergeRight',order:17},tablecell_merge_down:{label:G.cell.mergeDown,group:'tablecell',command:'cellMergeDown',order:18},tablecell_split_horizontal:{label:G.cell.splitHorizontal,group:'tablecell',command:'cellHorizontalSplit',order:19},tablecell_split_vertical:{label:G.cell.splitVertical,group:'tablecell',command:'cellVerticalSplit',order:20},tablecell_properties:{label:G.cell.title,group:'tablecellproperties',command:'cellProperties',order:21},tablerow:{label:G.row.menu,group:'tablerow',order:1,getItems:function(){return{tablerow_insertBefore:2,tablerow_insertAfter:2,tablerow_delete:2}; +}},tablerow_insertBefore:{label:G.row.insertBefore,group:'tablerow',command:'rowInsertBefore',order:5},tablerow_insertAfter:{label:G.row.insertAfter,group:'tablerow',command:'rowInsertAfter',order:10},tablerow_delete:{label:G.row.deleteRow,group:'tablerow',command:'rowDelete',order:15},tablecolumn:{label:G.column.menu,group:'tablecolumn',order:1,getItems:function(){return{tablecolumn_insertBefore:2,tablecolumn_insertAfter:2,tablecolumn_delete:2};}},tablecolumn_insertBefore:{label:G.column.insertBefore,group:'tablecolumn',command:'columnInsertBefore',order:5},tablecolumn_insertAfter:{label:G.column.insertAfter,group:'tablecolumn',command:'columnInsertAfter',order:10},tablecolumn_delete:{label:G.column.deleteColumn,group:'tablecolumn',command:'columnDelete',order:15}});if(F.contextMenu)F.contextMenu.addListener(function(H,I){if(!H||H.isReadOnly())return null;while(H){if(H.getName() in E)return{tablecell:2,tablerow:2,tablecolumn:2};H=H.getParent();}return null;});},getSelectedCells:n};j.add('tabletools',j.tabletools);})();e.buildTableMap=function(l){var m=l.$.rows,n=-1,o=[];for(var p=0;po&&(!r||!s||us){r=u;s=t;}}else{if(p&&t==o){r=u;break;}if(ts)){r=u;s=t;}}}if(r)r.focus();};(function(){j.add('templates',{requires:['dialog'],init:function(n){a.dialog.add('templates',a.getUrl(this.path+'dialogs/templates.js'));n.addCommand('templates',new a.dialogCommand('templates'));n.ui.addButton('Templates',{label:n.lang.templates.button,command:'templates'});}});var l={},m={};a.addTemplates=function(n,o){l[n]=o;};a.getTemplates=function(n){return l[n];};a.loadTemplates=function(n,o){var p=[];for(var q=0;q0)a.scriptLoader.load(p,o); +else setTimeout(o,0);};})();i.templates='default';i.templates_files=[a.getUrl('plugins/templates/templates/default.js')];i.templates_replaceContent=true;(function(){var l=function(){this.toolbars=[];this.focusCommandExecuted=false;};l.prototype.focus=function(){for(var n=0,o;o=this.toolbars[n++];)for(var p=0,q;q=o.items[p++];){if(q.focus){q.focus();return;}}};var m={toolbarFocus:{modes:{wysiwyg:1,source:1},exec:function(n){if(n.toolbox){n.toolbox.focusCommandExecuted=true;if(c)setTimeout(function(){n.toolbox.focus();},100);else n.toolbox.focus();}}}};j.add('toolbar',{init:function(n){var o=function(p,q){var r,s,t,u=n.lang.dir=='rtl';switch(q){case u?37:39:case 9:do{r=p.next;if(!r){s=p.toolbar.next;t=s&&s.items.length;while(t===0){s=s.next;t=s&&s.items.length;}if(s)r=s.items[0];}p=r;}while(p&&!p.focus)if(p)p.focus();else n.toolbox.focus();return false;case u?39:37:case 2000+9:do{r=p.previous;if(!r){s=p.toolbar.previous;t=s&&s.items.length;while(t===0){s=s.previous;t=s&&s.items.length;}if(s)r=s.items[t-1];}p=r;}while(p&&!p.focus)if(p)p.focus();else{var v=n.toolbox.toolbars[n.toolbox.toolbars.length-1].items;v[v.length-1].focus();}return false;case 27:n.focus();return false;case 13:case 32:p.execute();return false;}return true;};n.on('themeSpace',function(p){if(p.data.space==n.config.toolbarLocation){n.toolbox=new l();var q='cke_'+e.getNextNumber(),r=['');if(n.config.toolbarCanCollapse){var F=e.addFunction(function(){n.execCommand('toolbarCollapse');});n.on('destroy',function(){e.removeFunction(F);});var G='cke_'+e.getNextNumber();n.addCommand('toolbarCollapse',{exec:function(H){var I=a.document.getById(G),J=I.getPrevious(),K=H.getThemeSpace('contents'),L=J.getParent(),M=parseInt(K.$.style.height,10),N=L.$.offsetHeight,O=!J.isVisible();if(!O){J.hide();I.addClass('cke_toolbox_collapser_min');I.setAttribute('title',H.lang.toolbarExpand);}else{J.show();I.removeClass('cke_toolbox_collapser_min');I.setAttribute('title',H.lang.toolbarCollapse);}I.getFirst().setText(O?'â–²':'â—€');var P=L.$.offsetHeight-N;K.setStyle('height',M-P+'px');H.fire('resize');},modes:{wysiwyg:1,source:1}});r.push('','','');}p.data.html+=r.join('');}});n.addCommand('toolbarFocus',m.toolbarFocus);}});})();k.separator={render:function(l,m){m.push('');return{};}};i.toolbarLocation='top';i.toolbar_Basic=[['Bold','Italic','-','NumberedList','BulletedList','-','Link','Unlink','-','About']];i.toolbar_Full=[['Source','-','Save','NewPage','Preview','-','Templates'],['Cut','Copy','Paste','PasteText','PasteFromWord','-','Print','SpellChecker','Scayt'],['Undo','Redo','-','Find','Replace','-','SelectAll','RemoveFormat'],['Form','Checkbox','Radio','TextField','Textarea','Select','Button','ImageButton','HiddenField'],'/',['Bold','Italic','Underline','Strike','-','Subscript','Superscript'],['NumberedList','BulletedList','-','Outdent','Indent','Blockquote','CreateDiv'],['JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock'],['BidiLtr','BidiRtl'],['Link','Unlink','Anchor'],['Image','Flash','Table','HorizontalRule','Smiley','SpecialChar','PageBreak'],'/',['Styles','Format','Font','FontSize'],['TextColor','BGColor'],['Maximize','ShowBlocks','-','About']];i.toolbar='Full';i.toolbarCanCollapse=true;(function(){j.add('undo',{requires:['selection','wysiwygarea'],init:function(r){var s=new n(r),t=r.addCommand('undo',{exec:function(){if(s.undo()){r.selectionChange();this.fire('afterUndo');}},state:0,canUndo:false}),u=r.addCommand('redo',{exec:function(){if(s.redo()){r.selectionChange();this.fire('afterRedo'); +}},state:0,canUndo:false});s.onChange=function(){t.setState(s.undoable()?2:0);u.setState(s.redoable()?2:0);};function v(w){if(s.enabled&&w.data.command.canUndo!==false)s.save();};r.on('beforeCommandExec',v);r.on('afterCommandExec',v);r.on('saveSnapshot',function(){s.save();});r.on('contentDom',function(){r.document.on('keydown',function(w){if(!w.data.$.ctrlKey&&!w.data.$.metaKey)s.type(w);});});r.on('beforeModeUnload',function(){r.mode=='wysiwyg'&&s.save(true);});r.on('mode',function(){s.enabled=r.mode=='wysiwyg';s.onChange();});r.ui.addButton('Undo',{label:r.lang.undo,command:'undo'});r.ui.addButton('Redo',{label:r.lang.redo,command:'redo'});r.resetUndo=function(){s.reset();r.fire('saveSnapshot');};r.on('updateSnapshot',function(){if(s.currentImage&&new l(r).equals(s.currentImage))setTimeout(function(){s.update();},0);});}});j.undo={};var l=j.undo.Image=function(r){this.editor=r;var s=r.getSnapshot(),t=s&&r.getSelection();c&&s&&(s=s.replace(/\s+_cke_expando=".*?"/g,''));this.contents=s;this.bookmarks=t&&t.createBookmarks2(true);},m=/\b(?:href|src|name)="[^"]*?"/gi;l.prototype={equals:function(r,s){var t=this.contents,u=r.contents;if(c&&(b.ie7Compat||b.ie6Compat)){t=t.replace(m,'');u=u.replace(m,'');}if(t!=u)return false;if(s)return true;var v=this.bookmarks,w=r.bookmarks;if(v||w){if(!v||!w||v.length!=w.length)return false;for(var x=0;x25){this.save(false,null,false);this.modifiersCount=1;}}else if(!x){this.modifiersCount=0;this.typesCount++;if(this.typesCount>25){this.save(false,null,false);this.typesCount=1;}}},reset:function(){var r=this; +r.lastKeystroke=0;r.snapshots=[];r.index=-1;r.limit=r.editor.config.undoStackSize;r.currentImage=null;r.hasUndo=false;r.hasRedo=false;r.resetType();},resetType:function(){var r=this;r.typing=false;delete r.lastKeystroke;r.typesCount=0;r.modifiersCount=0;},fireChange:function(){var r=this;r.hasUndo=!!r.getNextImage(true);r.hasRedo=!!r.getNextImage(false);r.resetType();r.onChange();},save:function(r,s,t){var v=this;var u=v.snapshots;if(!s)s=new l(v.editor);if(s.contents===false)return false;if(v.currentImage&&s.equals(v.currentImage,r))return false;u.splice(v.index+1,u.length-v.index-1);if(u.length==v.limit)u.shift();v.index=u.push(s)-1;v.currentImage=s;if(t!==false)v.fireChange();return true;},restoreImage:function(r){var t=this;t.editor.loadSnapshot(r.contents);if(r.bookmarks)t.editor.getSelection().selectBookmarks(r.bookmarks);else if(c){var s=t.editor.document.getBody().$.createTextRange();s.collapse(true);s.select();}t.index=r.index;t.update();t.fireChange();},getNextImage:function(r){var w=this;var s=w.snapshots,t=w.currentImage,u,v;if(t)if(r)for(v=w.index-1;v>=0;v--){u=s[v];if(!t.equals(u,true)){u.index=v;return u;}}else for(v=w.index+1;v]*>\s*(?:]*>| |\u00A0| )?\s*(:?<\/\1>)?(?=\s*$|<\/body>)/gi,n=d.walker.whitespaces(true);function o(A){if(A.getType()==3)return A.getSelectedElement().isReadOnly();else return A.getCommonAncestor().isReadOnly();};function p(A){if(this.mode=='wysiwyg'){this.focus();var B=this.getSelection();if(o(B))return;var C=A.data;this.fire('saveSnapshot');if(this.dataProcessor)C=this.dataProcessor.toHtml(C);if(c){var D=B.isLocked;if(D)B.unlock();var E=B.getNative();if(E.type=='Control')E.clear();else if(B.getType()==2){var F=B.getRanges()[0],G=F&&F.endContainer;if(G&&G.type==1&&G.getAttribute('contenteditable')=='false'&&F.checkBoundaryOfElement(G,2)){F.setEndAfter(F.endContainer); +F.deleteContents();}}try{E.createRange().pasteHTML(C);}catch(I){}if(D)this.getSelection().lock();}else this.document.$.execCommand('inserthtml',false,C);if(b.webkit){this.document.$.execCommand('inserthtml',false,'');var H=this.document.getById('cke_paste_marker');H.scrollIntoView();H.remove();}e.setTimeout(function(){this.fire('saveSnapshot');},0,this);}};function q(A){if(this.mode=='wysiwyg'){this.focus();var B=this.getSelection();if(o(B))return;this.fire('saveSnapshot');var C=B.getRanges(),D=A.data,E=D.getName(),F=f.$block[E],G=B.isLocked;if(G)B.unlock();var H,I,J,K;for(var L=C.length-1;L>=0;L--){H=C[L];H.deleteContents();I=!L&&D||D.clone(true);var M,N;if(F)while((M=H.getCommonAncestor(false,true))&&(N=f[M.getName()])&&!(N&&N[E])){if(M.getName() in f.span)H.splitElement(M);else if(H.checkStartOfBlock()&&H.checkEndOfBlock()){H.setStartBefore(M);H.collapse(true);M.remove();}else H.splitBlock();}H.insertNode(I);if(!J)J=I;}H.moveToPosition(J,4);if(F){var O=J.getNext(n),P=O&&O.type==1&&O.getName();if(P&&f.$block[P]&&f[P]['#'])H.moveToElementEditStart(O);}B.selectRanges([H]);if(G)this.getSelection().lock();e.setTimeout(function(){this.fire('saveSnapshot');},0,this);}};function r(A){if(!A.checkDirty())setTimeout(function(){A.resetDirty();},0);};var s=d.walker.whitespaces(true),t=d.walker.bookmark(false,true);function u(A){return s(A)&&t(A);};function v(A){return A.type==3&&e.trim(A.getText()).match(/^(?: |\xa0)$/);};function w(A){if(A.isLocked){A.unlock();setTimeout(function(){A.lock();},0);}};function x(A){return A.getOuterHtml().match(m);};s=d.walker.whitespaces(true);function y(A){var B=A.window,C=A.document,D=A.document.getBody(),E=D.getChildren().count();if(!E||E==1&&D.getFirst().hasAttribute('_moz_editor_bogus_node')){r(A);var F=A.element.getDocument(),G=F.getDocumentElement(),H=G.$.scrollTop,I=G.$.scrollLeft,J=C.$.createEvent('KeyEvents');J.initKeyEvent('keypress',true,true,B.$,false,false,false,false,0,32);C.$.dispatchEvent(J);if(H!=G.$.scrollTop||I!=G.$.scrollLeft)F.getWindow().$.scrollTo(I,H);E&&D.getFirst().remove();C.getBody().appendBogus();var K=new d.range(C);K.setStartAt(D,1);K.select();}};function z(A){var B=A.editor,C=A.data.path,D=C.blockLimit,E=A.data.selection,F=E.getRanges()[0],G=B.document.getBody(),H=B.config.enterMode;b.gecko&&y(B);if(H!=2&&F.collapsed&&D.getName()=='body'&&!C.block){B.fire('updateSnapshot');r(B);c&&w(E);var I=F.fixBlock(true,B.config.enterMode==3?'div':'p');if(c){var J=I.getFirst(u); +J&&v(J)&&J.remove();}if(x(I)){var K=I.getNext(s);if(K&&K.type==1&&!l[K.getName()]){F.moveToElementEditStart(K);I.remove();}else{K=I.getPrevious(s);if(K&&K.type==1&&!l[K.getName()]){F.moveToElementEditEnd(K);I.remove();}}}F.select();if(!c)B.selectionChange();}var L=new d.range(B.document),M=new d.walker(L);L.selectNodeContents(G);M.evaluator=function(O){return O.type==1&&O.getName() in l;};M.guard=function(O,P){return!(O.type==3&&s(O)||P);};if(M.previous()){B.fire('updateSnapshot');r(B);c&&w(E);var N;if(H!=2)N=G.append(new h(H==1?'p':'div'));else N=G;if(!c)N.appendBogus();}};j.add('wysiwygarea',{requires:['editingblock'],init:function(A){var B=A.config.enterMode!=2?A.config.enterMode==3?'div':'p':false,C=A.lang.editorTitle.replace('%1',A.name),D;A.on('editingBlockReady',function(){var J,K,L,M,N,O,P=b.isCustomDomain(),Q=function(T){if(K)K.remove();var U='document.open();'+(P?'document.domain="'+document.domain+'";':'')+'document.close();';K=h.createFromHtml('');if(document.location.protocol=='chrome:')a.event.useCapture=true;K.on('load',function(Y){N=1;Y.removeListener();var Z=K.getFrameDocument().$;Z.open('text/html','replace');Z.write(T);Z.close();});if(document.location.protocol=='chrome:')a.event.useCapture=false;var V=A.element,W=b.gecko&&!V.isVisible(),X={};if(W){V.show();X={position:V.getStyle('position'),top:V.getStyle('top')};V.setStyles({position:'absolute',top:'-3000px'});}J.append(K);if(W)setTimeout(function(){V.hide();V.setStyles(X);},1000);};D=e.addFunction(S);var R='';function S(T){if(!N)return;N=0;A.fire('ariaWidget',K);var U=T.document,V=U.body,W=U.getElementById('cke_actscrpt');W.parentNode.removeChild(W);V.spellcheck=!A.config.disableNativeSpellChecker;if(c){V.hideFocus=true;V.disabled=true;V.contentEditable=true;V.removeAttribute('disabled');}else setTimeout(function(){if(b.gecko&&b.version>=10900||b.opera)U.$.body.contentEditable=true;else if(b.webkit)U.$.body.parentNode.contentEditable=true;else U.$.designMode='on';},0);b.gecko&&e.setTimeout(y,0,null,A);T=A.window=new d.window(T);U=A.document=new g(U);U.on('dblclick',function(aa){var ab=aa.data.getTarget(),ac={element:ab,dialog:''}; +A.fire('doubleclick',ac);ac.dialog&&A.openDialog(ac.dialog);});if(!(c||b.opera))U.on('mousedown',function(aa){var ab=aa.data.getTarget();if(ab.is('img','hr','input','textarea','select'))A.getSelection().selectElement(ab);});if(b.gecko)U.on('mouseup',function(aa){if(aa.data.$.button==2){var ab=aa.data.getTarget();if(!ab.getOuterHtml().replace(m,'')){var ac=new d.range(U);ac.moveToElementEditStart(ab);ac.select(true);}}});U.on('click',function(aa){aa=aa.data;if(aa.getTarget().is('a')&&aa.$.button!=2)aa.preventDefault();});if(b.webkit){U.on('click',function(aa){if(aa.data.getTarget().is('input','select'))aa.data.preventDefault();});U.on('mouseup',function(aa){if(aa.data.getTarget().is('input','textarea'))aa.data.preventDefault();});}if(c&&U.$.compatMode=='CSS1Compat'||b.gecko||b.opera){var X=U.getDocumentElement();X.on('mousedown',function(aa){if(aa.data.getTarget().equals(X)){if(b.gecko&&b.version>=10900)H();I.focus();}});}T.on('blur',function(){A.focusManager.blur();});T.on('focus',function(){var aa=A.document;if(b.gecko&&b.version>=10900)H();else if(b.opera)aa.getBody().focus();A.focusManager.focus();});var Y=A.keystrokeHandler;if(Y)Y.attach(U);if(c){U.getDocumentElement().addClass(U.$.compatMode);U.on('keydown',function(aa){var ab=aa.data.getKeystroke();if(ab in {8:1,46:1}){var ac=A.getSelection(),ad=ac.getSelectedElement();if(ad){A.fire('saveSnapshot');var ae=ac.getRanges()[0].createBookmark();ad.remove();ac.selectBookmarks([ae]);A.fire('saveSnapshot');aa.data.preventDefault();}}});if(U.$.compatMode=='CSS1Compat'){var Z={33:1,34:1};U.on('keydown',function(aa){if(aa.data.getKeystroke() in Z)setTimeout(function(){A.getSelection().scrollIntoView();},0);});}}if(A.contextMenu)A.contextMenu.addTarget(U,A.config.browserContextMenuOnCtrl!==false);setTimeout(function(){A.fire('contentDom');if(O){A.mode='wysiwyg';A.fire('mode');O=false;}L=false;if(M){A.focus();M=false;}setTimeout(function(){A.fire('dataReady');},0);try{A.document.$.execCommand('enableObjectResizing',false,!A.config.disableObjectResizing);}catch(aa){}try{A.document.$.execCommand('enableInlineTableEditing',false,!A.config.disableNativeTableHandles);}catch(ab){}if(c)setTimeout(function(){if(A.document){var ac=A.document.$.body;ac.runtimeStyle.marginBottom='0px';ac.runtimeStyle.marginBottom='';}},1000);},0);};A.addMode('wysiwyg',{load:function(T,U,V){J=T;if(c&&b.quirks)T.setStyle('position','relative');A.mayBeDirty=true;O=true;if(V)this.loadSnapshotData(U);else this.loadData(U);},loadData:function(T){L=true; +var U=A.config,V=U.fullPage,W=U.docType,X='';!V&&(X=e.buildStyleHtml(A.config.contentsCss)+X);var Y=U.baseHref?'':'';if(V)T=T.replace(/]*>/i,function(Z){A.docType=W=Z;return '';});if(A.dataProcessor)T=A.dataProcessor.toHtml(T,B);if(V){if(!/]/.test(T))T=''+T;if(!/]/.test(T))T=''+T+'';if(!/]/.test(T))T=T.replace(/]*>/,'$&');else if(!/]/.test(T))T=T.replace(/]*>/,'$&');Y&&(T=T.replace(//,'$&'+Y));T=T.replace(/<\/head\s*>/,X+'$&');T=W+T;}else T=U.docType+''+''+''+C+''+Y+X+''+''+T+'';T+=R;this.onDispose();Q(T);},getData:function(){var T=A.config,U=T.fullPage,V=U&&A.docType,W=K.getFrameDocument(),X=U?W.getDocumentElement().getOuterHtml():W.getBody().getHtml();if(A.dataProcessor)X=A.dataProcessor.toDataFormat(X,B);if(T.ignoreEmptyParagraph)X=X.replace(m,'');if(V)X=V+'\n'+X;return X;},getSnapshotData:function(){return K.getFrameDocument().getBody().getHtml();},loadSnapshotData:function(T){K.getFrameDocument().getBody().setHtml(T);},onDispose:function(){if(!A.document)return;A.document.getDocumentElement().clearCustomData();A.document.getBody().clearCustomData();A.window.clearCustomData();A.document.clearCustomData();K.clearCustomData();K.remove();},unload:function(T){this.onDispose();A.window=A.document=K=J=M=null;A.fire('contentDomUnload');},focus:function(){if(L)M=true;else if(b.opera&&A.document){A.document.getBody().focus();A.selectionChange();}else if(!b.opera&&A.window){A.window.focus();A.selectionChange();}}});A.on('insertHtml',p,null,null,20);A.on('insertElement',q,null,null,20);A.on('selectionChange',z,null,null,1);});var E;A.on('contentDom',function(){var J=A.document.getElementsByTag('title').getItem(0);J.setAttribute('_cke_title',A.document.$.title);A.document.$.title=C;});if(b.ie8Compat){A.addCss('html.CSS1Compat [contenteditable=false]{ min-height:0 !important;}');var F=[];for(var G in f.$removeEmpty)F.push('html.CSS1Compat '+G+'[contenteditable=false]');A.addCss(F.join(',')+'{ display:inline-block;}');}function H(J){e.tryThese(function(){A.document.$.designMode='on';setTimeout(function(){A.document.$.designMode='off'; +A.document.getBody().focus();},50);},function(){A.document.$.designMode='off';var K=A.document.getBody();K.setAttribute('contentEditable',false);K.setAttribute('contentEditable',true);!J&&H(1);});};if(b.gecko||c||b.opera){var I;A.on('uiReady',function(){I=A.container.append(h.createFromHtml(''));I.on('focus',function(){A.focus();});});A.on('destroy',function(){e.removeFunction(D);I.clearCustomData();});}A.on('insertElement',function(J){var K=J.data;if(K.type==1&&(K.is('input')||K.is('textarea')))if(!K.isReadOnly()){K.setAttribute('contentEditable',false);K.setCustomData('_cke_notReadOnly',1);}});}});if(b.gecko)(function(){var A=document.body;if(!A)window.addEventListener('load',arguments.callee,false);else{var B=A.getAttribute('onpageshow');A.setAttribute('onpageshow',(B?B+';':'')+'event.persisted && (function(){'+'var allInstances = CKEDITOR.instances, editor, doc;'+'for ( var i in allInstances )'+'{'+'\teditor = allInstances[ i ];'+'\tdoc = editor.document;'+'\tif ( doc )'+'\t{'+'\t\tdoc.$.designMode = "off";'+'\t\tdoc.$.designMode = "on";'+'\t}'+'}'+'})();');}})();})();i.disableObjectResizing=false;i.disableNativeTableHandles=true;i.disableNativeSpellChecker=true;i.ignoreEmptyParagraph=true;j.add('wsc',{requires:['dialog'],init:function(l){var m='checkspell',n=l.addCommand(m,new a.dialogCommand(m));n.modes={wysiwyg:!b.opera&&document.domain==window.location.hostname};l.ui.addButton('SpellChecker',{label:l.lang.spellCheck.toolbar,command:m});a.dialog.add(m,this.path+'dialogs/wsc.js');}});i.wsc_customerId=i.wsc_customerId||'1:ua3xw1-2XyGJ3-GWruD3-6OFNT1-oXcuB1-nR6Bp4-hgQHc-EcYng3-sdRXG3-NOfFk';i.wsc_customLoaderScript=i.wsc_customLoaderScript||null;a.DIALOG_RESIZE_NONE=0;a.DIALOG_RESIZE_WIDTH=1;a.DIALOG_RESIZE_HEIGHT=2;a.DIALOG_RESIZE_BOTH=3;(function(){function l(N){return!!this._.tabs[N][0].$.offsetHeight;};function m(){var R=this;var N=R._.currentTabId,O=R._.tabIdList.length,P=e.indexOf(R._.tabIdList,N)+O;for(var Q=P-1;Q>P-O;Q--){if(l.call(R,R._.tabIdList[Q%O]))return R._.tabIdList[Q%O];}return null;};function n(){var R=this;var N=R._.currentTabId,O=R._.tabIdList.length,P=e.indexOf(R._.tabIdList,N);for(var Q=P+1;Q1){S._.tabBarMode=true;S._.tabs[S._.currentTabId][0].focus();W=1;}else if((af==37||af==39)&&S._.tabBarMode){ai=af==(ag?39:37)?m.call(S):n.call(S);S.selectPage(ai);S._.tabs[ai][0].focus();W=1;}else if((af==13||af==32)&&S._.tabBarMode){aj.selectPage(aj._.currentTabId);aj._.tabBarMode=false;aj._.currentFocusIndex=-1;V(true);W=1;}if(W){ae.stop();ae.data.preventDefault();}};function Y(ae){W&&ae.data.preventDefault();};var Z=this._.element;this.on('show',function(){Z.on('keydown',X,this,null,0);if(b.opera||b.gecko&&b.mac)Z.on('keypress',Y,this);});this.on('hide',function(){Z.removeListener('keydown',X);if(b.opera||b.gecko&&b.mac)Z.removeListener('keypress',Y);});this.on('iframeAdded',function(ae){var af=new g(ae.data.iframe.$.contentWindow.document);af.on('keydown',X,this,null,0);});this.on('show',function(){var ai=this;U();if(N.config.dialog_startupFocusTab&&S._.pageCount>1){S._.tabBarMode=true;S._.tabs[S._.currentTabId][0].focus();}else if(!ai._.hasFocus){ai._.currentFocusIndex=-1;if(P.onFocus){var ae=P.onFocus.call(ai);ae&&ae.focus();}else V(true);if(ai._.editor.mode=='wysiwyg'&&c){var af=N.document.$.selection,ag=af.createRange();if(ag)if(ag.parentElement&&ag.parentElement().ownerDocument==N.document.$||ag.item&&ag.item(0).ownerDocument==N.document.$){var ah=document.body.createTextRange();ah.moveToElementText(ai.getElement().getFirst().$);ah.collapse(true);ah.select();}}}},this,null,4294967295);if(b.ie6Compat)this.on('load',function(ae){var af=this.getElement(),ag=af.getFirst();ag.remove();ag.appendTo(af);},this);w(this);x(this);new d.text(P.title,a.document).appendTo(this.parts.title);for(var aa=0;aa0?O:0)+'px',top:(P>0?P:0)+'px'});};})(),getPosition:function(){return e.extend({},this._.position);},show:function(){var N=this._.editor;if(N.mode=='wysiwyg'&&c){var O=N.getSelection();O&&O.lock();}var P=this._.element,Q=this.definition;if(!(P.getParent()&&P.getParent().equals(a.document.getBody())))P.appendTo(a.document.getBody());else P.setStyle('display','block');if(b.gecko&&b.version<10900){var R=this.parts.dialog;R.setStyle('position','absolute');setTimeout(function(){R.setStyle('position','fixed');},0);}this.resize(Q.minWidth,Q.minHeight);this.reset();this.selectPage(this.definition.contents[0].id);if(a.dialog._.currentZIndex===null)a.dialog._.currentZIndex=this._.editor.config.baseFloatZIndex;this._.element.getFirst().setStyle('z-index',a.dialog._.currentZIndex+=10);if(a.dialog._.currentTop===null){a.dialog._.currentTop=this;this._.parentDialog=null;B(this._.editor);P.on('keydown',F);P.on(b.opera?'keypress':'keyup',G);for(var S in {keyup:1,keydown:1,keypress:1})P.on(S,M);}else{this._.parentDialog=a.dialog._.currentTop;var T=this._.parentDialog.getElement().getFirst();T.$.style.zIndex-=Math.floor(this._.editor.config.baseFloatZIndex/2);a.dialog._.currentTop=this;}H(this,this,'\x1b',null,function(){this.getButton('cancel')&&this.getButton('cancel').click(); +});this._.hasFocus=false;e.setTimeout(function(){var U=a.document.getWindow().getViewPaneSize(),V=this.getSize();this.move((U.width-Q.minWidth)/2,(U.height-V.height)/2);this.parts.dialog.setStyle('visibility','');this.fireOnce('load',{});this.fire('show',{});this._.editor.fire('dialogShow',this);this.foreach(function(W){W.setInitValue&&W.setInitValue();});},100,this);},foreach:function(N){var Q=this;for(var O in Q._.contents)for(var P in Q._.contents[O])N(Q._.contents[O][P]);return Q;},reset:(function(){var N=function(O){if(O.reset)O.reset(1);};return function(){this.foreach(N);return this;};})(),setupContent:function(){var N=arguments;this.foreach(function(O){if(O.setup)O.setup.apply(O,N);});},commitContent:function(){var N=arguments;this.foreach(function(O){if(O.commit)O.commit.apply(O,N);});},hide:function(){if(!this.parts.dialog.isVisible())return;this.fire('hide',{});this._.editor.fire('dialogHide',this);var N=this._.element;N.setStyle('display','none');this.parts.dialog.setStyle('visibility','hidden');I(this);while(a.dialog._.currentTop!=this)a.dialog._.currentTop.hide();if(!this._.parentDialog)C();else{var O=this._.parentDialog.getElement().getFirst();O.setStyle('z-index',parseInt(O.$.style.zIndex,10)+Math.floor(this._.editor.config.baseFloatZIndex/2));}a.dialog._.currentTop=this._.parentDialog;if(!this._.parentDialog){a.dialog._.currentZIndex=null;N.removeListener('keydown',F);N.removeListener(b.opera?'keypress':'keyup',G);for(var P in {keyup:1,keydown:1,keypress:1})N.removeListener(P,M);var Q=this._.editor;Q.focus();if(Q.mode=='wysiwyg'&&c){var R=Q.getSelection();R&&R.unlock(true);}}else a.dialog._.currentZIndex-=10;delete this._.parentDialog;this.foreach(function(S){S.resetInitValue&&S.resetInitValue();});},addPage:function(N){var Z=this;var O=[],P=N.label?' title="'+e.htmlEncode(N.label)+'"':'',Q=N.elements,R=a.dialog._.uiElementBuilders.vbox.build(Z,{type:'vbox',className:'cke_dialog_page_contents',children:N.elements,expand:!!N.expand,padding:N.padding,style:N.style||'width: 100%; height: 100%;'},O),S=h.createFromHtml(O.join(''));S.setAttribute('role','tabpanel');var T=b,U='cke_'+N.id+'_'+e.getNextNumber(),V=h.createFromHtml(['0?' cke_last':'cke_first',P,!!N.hidden?' style="display:none"':'',' id="',U,'"',T.gecko&&T.version>=10900&&!T.hc?'':' href="javascript:void(0)"',' tabIndex="-1"',' hidefocus="true"',' role="tab">',N.label,''].join(''));S.setAttribute('aria-labelledby',U);Z._.tabs[N.id]=[V,S];Z._.tabIdList.push(N.id); +!N.hidden&&Z._.pageCount++;Z._.lastTab=V;Z.updateStyle();var W=Z._.contents[N.id]={},X,Y=R.getChild();while(X=Y.shift()){W[X.id]=X;if(typeof X.getChild=='function')Y.push.apply(Y,X.getChild());}S.setAttribute('name',N.id);S.appendTo(Z.parts.contents);V.unselectable();Z.parts.tabs.append(V);if(N.accessKey){H(Z,Z,'CTRL+'+N.accessKey,K,J);Z._.accessKeyMap['CTRL+'+N.accessKey]=N.id;}},selectPage:function(N){if(this._.currentTabId==N)return;if(this.fire('selectPage',{page:N,currentPage:this._.currentTabId})===true)return;for(var O in this._.tabs){var P=this._.tabs[O][0],Q=this._.tabs[O][1];if(O!=N){P.removeClass('cke_dialog_tab_selected');Q.hide();}Q.setAttribute('aria-hidden',O!=N);}var R=this._.tabs[N];R[0].addClass('cke_dialog_tab_selected');if(b.ie6Compat||b.ie7Compat){o(R[1]);R[1].show();setTimeout(function(){o(R[1],true);},0);}else R[1].show();this._.currentTabId=N;this._.currentTabIndex=e.indexOf(this._.tabIdList,N);},updateStyle:function(){this.parts.dialog[(this._.pageCount===1?'add':'remove')+'Class']('cke_single_page');},hidePage:function(N){var P=this;var O=P._.tabs[N]&&P._.tabs[N][0];if(!O||P._.pageCount==1)return;else if(N==P._.currentTabId)P.selectPage(m.call(P));O.hide();P._.pageCount--;P.updateStyle();},showPage:function(N){var P=this;var O=P._.tabs[N]&&P._.tabs[N][0];if(!O)return;O.show();P._.pageCount++;P.updateStyle();},getElement:function(){return this._.element;},getName:function(){return this._.name;},getContentElement:function(N,O){var P=this._.contents[N];return P&&P[O];},getValueOf:function(N,O){return this.getContentElement(N,O).getValue();},setValueOf:function(N,O,P){return this.getContentElement(N,O).setValue(P);},getButton:function(N){return this._.buttons[N];},click:function(N){return this._.buttons[N].click();},disableButton:function(N){return this._.buttons[N].disable();},enableButton:function(N){return this._.buttons[N].enable();},getPageCount:function(){return this._.pageCount;},getParentEditor:function(){return this._.editor;},getSelectedElement:function(){return this.getParentEditor().getSelection().getSelectedElement();},addFocusable:function(N,O){var Q=this;if(typeof O=='undefined'){O=Q._.focusList.length;Q._.focusList.push(new p(Q,N,O));}else{Q._.focusList.splice(O,0,new p(Q,N,O));for(var P=O+1;PY.width-X.width-S)ad=Y.width-X.width+T[1];else ad=P.x;if(P.y+T[0]Y.height-X.height-S)ae=Y.height-X.height+T[2];else ae=P.y;N.move(ad,ae);W.data.preventDefault();};function V(W){a.document.removeListener('mousemove',U);a.document.removeListener('mouseup',V);if(b.ie6Compat){var X=A.getChild(0).getFrameDocument();X.removeListener('mousemove',U);X.removeListener('mouseup',V);}};N.parts.title.on('mousedown',function(W){N._.updateSize=true;O={x:W.data.$.screenX,y:W.data.$.screenY};a.document.on('mousemove',U);a.document.on('mouseup',V);P=N.getPosition();if(b.ie6Compat){var X=A.getChild(0).getFrameDocument();X.on('mousemove',U);X.on('mouseup',V);}W.data.preventDefault();},N);};function x(N){var O=N.definition,P=O.minWidth||0,Q=O.minHeight||0,R=O.resizable,S=N.getParentEditor().skin.margins||[0,0,0,0];function T(ae,af){ae.y+=af;};function U(ae,af){ae.x2+=af;};function V(ae,af){ae.y2+=af;};function W(ae,af){ae.x+=af;};var X=null,Y=null,Z=N._.editor.config.magnetDistance,aa=['tl','t','tr','l','r','bl','b','br'];function ab(ae){var af=ae.listenerData.part,ag=N.getSize();Y=N.getPosition();e.extend(Y,{x2:Y.x+ag.width,y2:Y.y+ag.height});X={x:ae.data.$.screenX,y:ae.data.$.screenY};a.document.on('mousemove',ac,N,{part:af});a.document.on('mouseup',ad,N,{part:af});if(b.ie6Compat){var ah=A.getChild(0).getFrameDocument();ah.on('mousemove',ac,N,{part:af});ah.on('mouseup',ad,N,{part:af});}ae.data.preventDefault();};function ac(ae){var af=ae.data.$.screenX,ag=ae.data.$.screenY,ah=af-X.x,ai=ag-X.y,aj=a.document.getWindow().getViewPaneSize(),ak=ae.listenerData.part;if(ak.search('t')!=-1)T(Y,ai);if(ak.search('l')!=-1)W(Y,ah);if(ak.search('b')!=-1)V(Y,ai);if(ak.search('r')!=-1)U(Y,ah);X={x:af,y:ag};var al,am,an,ao;if(Y.x+S[3]aj.width-Z)an=aj.width+S[1];else if(ak.search('r')!=-1&&Y.x2-Y.xaj.height-Z)ao=aj.height+S[2];else if(ak.search('b')!=-1&&Y.y2-Y.y'];if(b.ie6Compat){var V=b.isCustomDomain(),W="";U.push('');}U.push('');T=h.createFromHtml(U.join(''));T.setOpacity(Q!=undefined?Q:0.5);T.appendTo(a.document.getBody());z[S]=T;}else T.show();A=T;var X=function(){var aa=O.getViewPaneSize();T.setStyles({width:aa.width+'px',height:aa.height+'px'});},Y=function(){var aa=O.getScrollPosition(),ab=a.dialog._.currentTop;T.setStyles({left:aa.x+'px',top:aa.y+'px'});do{var ac=ab.getPosition();ab.move(ac.x,ac.y);}while(ab=ab._.parentDialog)};y=X;O.on('resize',X);X();if(b.ie6Compat){var Z=function(){Y();arguments.callee.prevScrollHandler.apply(this,arguments);};O.$.setTimeout(function(){Z.prevScrollHandler=window.onscroll||(function(){});window.onscroll=Z;},0);Y();}};function C(){if(!A)return;var N=a.document.getWindow();A.hide();N.removeListener('resize',y);if(b.ie6Compat)N.$.setTimeout(function(){var O=window.onscroll&&window.onscroll.prevScrollHandler;window.onscroll=O||null;},0);y=null;};function D(){for(var N in z)z[N].remove();z={};};var E={},F=function(N){var O=N.data.$.ctrlKey||N.data.$.metaKey,P=N.data.$.altKey,Q=N.data.$.shiftKey,R=String.fromCharCode(N.data.$.keyCode),S=E[(O?'CTRL+':'')+(P?'ALT+':'')+(Q?'SHIFT+':'')+R];if(!S||!S.length)return;S=S[S.length-1];S.keydown&&S.keydown.call(S.uiElement,S.dialog,S.key);N.data.preventDefault();},G=function(N){var O=N.data.$.ctrlKey||N.data.$.metaKey,P=N.data.$.altKey,Q=N.data.$.shiftKey,R=String.fromCharCode(N.data.$.keyCode),S=E[(O?'CTRL+':'')+(P?'ALT+':'')+(Q?'SHIFT+':'')+R];if(!S||!S.length)return;S=S[S.length-1];if(S.keyup){S.keyup.call(S.uiElement,S.dialog,S.key);N.data.preventDefault();}},H=function(N,O,P,Q,R){var S=E[P]||(E[P]=[]);S.push({uiElement:N,dialog:O,key:P,keyup:R||N.accessKeyUp,keydown:Q||N.accessKeyDown});},I=function(N){for(var O in E){var P=E[O];for(var Q=P.length-1;Q>=0;Q--){if(P[Q].dialog==N||P[Q].uiElement==N)P.splice(Q,1); +}if(P.length===0)delete E[O];}},J=function(N,O){if(N._.accessKeyMap[O])N.selectPage(N._.accessKeyMap[O]);},K=function(N,O){},L={27:1,13:1},M=function(N){if(N.data.getKeystroke() in L)N.data.stopPropagation();};(function(){k.dialog={uiElement:function(N,O,P,Q,R,S,T){if(arguments.length<4)return;var U=(Q.call?Q(O):Q)||'div',V=['<',U,' '],W=(R&&R.call?R(O):R)||{},X=(S&&S.call?S(O):S)||{},Y=(T&&T.call?T.call(this,N,O):T)||'',Z=this.domId=X.id||e.getNextId()+'_uiElement',aa=this.id=O.id,ab;X.id=Z;var ac={};if(O.type)ac['cke_dialog_ui_'+O.type]=1;if(O.className)ac[O.className]=1;var ad=X['class']&&X['class'].split?X['class'].split(' '):[];for(ab=0;ab=0;ab--){if(af[ab]==='')af.splice(ab,1);}if(af.length>0)X.style=(X.style?X.style+'; ':'')+af.join('; ');for(ab in X)V.push(ab+'="'+e.htmlEncode(X[ab])+'" ');V.push('>',Y,'');P.push(V.join(''));(this._||(this._={})).dialog=N;if(typeof O.isChanged=='boolean')this.isChanged=function(){return O.isChanged;};if(typeof O.isChanged=='function')this.isChanged=O.isChanged;a.event.implementOn(this);this.registerEvents(O);if(this.accessKeyUp&&this.accessKeyDown&&O.accessKey)H(this,N,'CTRL+'+O.accessKey);var ag=this;N.on('load',function(){if(ag.getInputElement())ag.getInputElement().on('focus',function(){N._.tabBarMode=false;N._.hasFocus=true;ag.fire('focus');},ag);});if(this.keyboardFocusable){this.tabIndex=O.tabIndex||0;this.focusIndex=N._.focusList.push(this)-1;this.on('focus',function(){N._.currentFocusIndex=ag.focusIndex;});}e.extend(this,O);},hbox:function(N,O,P,Q,R){if(arguments.length<4)return;this._||(this._={});var S=this._.children=O,T=R&&R.widths||null,U=R&&R.height||null,V={},W,X=function(){var Z=[''];for(W=0;W0)Z.push('style="'+ab.join('; ')+'" ');Z.push('>',P[W],'');}Z.push('');return Z.join('');},Y={role:'presentation'}; +R&&R.align&&(Y.align=R.align);k.dialog.uiElement.call(this,N,R||{type:'hbox'},Q,'table',V,Y,X);},vbox:function(N,O,P,Q,R){if(arguments.length<3)return;this._||(this._={});var S=this._.children=O,T=R&&R.width||null,U=R&&R.heights||null,V=function(){var W=['');for(var X=0;X');}W.push('
    0)W.push('style="',Y.join('; '),'" ');W.push(' class="cke_dialog_ui_vbox_child">',P[X],'
    ');return W.join('');};k.dialog.uiElement.call(this,N,R||{type:'vbox'},Q,'div',null,{role:'presentation'},V);}};})();k.dialog.uiElement.prototype={getElement:function(){return a.document.getById(this.domId);},getInputElement:function(){return this.getElement();},getDialog:function(){return this._.dialog;},setValue:function(N,O){this.getInputElement().setValue(N);!O&&this.fire('change',{value:N});return this;},getValue:function(){return this.getInputElement().getValue();},isChanged:function(){return false;},selectParentTab:function(){var Q=this;var N=Q.getInputElement(),O=N,P;while((O=O.getParent())&&O.$.className.search('cke_dialog_page_contents')==-1){}if(!O)return Q;P=O.getAttribute('name');if(Q._.dialog._.currentTabId!=P)Q._.dialog.selectPage(P);return Q;},focus:function(){this.selectParentTab().getInputElement().focus();return this;},registerEvents:function(N){var O=/^on([A-Z]\w+)/,P,Q=function(S,T,U,V){T.on('load',function(){S.getInputElement().on(U,V,S);});};for(var R in N){if(!(P=R.match(O)))continue;if(this.eventProcessors[R])this.eventProcessors[R].call(this,this._.dialog,N[R]);else Q(this,this._.dialog,P[1].toLowerCase(),N[R]);}return this;},eventProcessors:{onLoad:function(N,O){N.on('load',O,this);},onShow:function(N,O){N.on('show',O,this);},onHide:function(N,O){N.on('hide',O,this);}},accessKeyDown:function(N,O){this.focus();},accessKeyUp:function(N,O){},disable:function(){var N=this.getInputElement();N.setAttribute('disabled','true');N.addClass('cke_disabled');},enable:function(){var N=this.getInputElement(); +N.removeAttribute('disabled');N.removeClass('cke_disabled');},isEnabled:function(){return!this.getInputElement().getAttribute('disabled');},isVisible:function(){return this.getInputElement().isVisible();},isFocusable:function(){if(!this.isEnabled()||!this.isVisible())return false;return true;}};k.dialog.hbox.prototype=e.extend(new k.dialog.uiElement(),{getChild:function(N){var O=this;if(arguments.length<1)return O._.children.concat();if(!N.splice)N=[N];if(N.length<2)return O._.children[N[0]];else return O._.children[N[0]]&&O._.children[N[0]].getChild?O._.children[N[0]].getChild(N.slice(1,N.length)):null;}},true);k.dialog.vbox.prototype=new k.dialog.hbox();(function(){var N={build:function(O,P,Q){var R=P.children,S,T=[],U=[];for(var V=0;V',P.name,'');return Q.join('');}};a.style.getStyleText=function(P){var Q=P._ST;if(Q)return Q;Q=P.styles;var R=P.attributes&&P.attributes.style||'',S='';if(R.length)R=R.replace(n,';');for(var T in Q){var U=Q[T],V=(T+':'+U).replace(n,';');if(U=='inherit')S+=V;else R+=V;}if(R.length)R=L(R);R+=S;return P._ST=R;};function o(P){var al=this;var Q=P.document;if(P.collapsed){var R=E(al,Q);P.insertNode(R);P.moveToPosition(R,2);return;}var S=al.element,T=al._.definition,U,V=f[S]||(U=true,f.span);P.enlarge(1);P.trim();var W=P.createBookmark(),X=W.startNode,Y=W.endNode,Z=X,aa;while(Z){var ab=false;if(Z.equals(Y)){Z=null;ab=true;}else{var ac=Z.type,ad=ac==1?Z.getName():null;if(ad&&Z.getAttribute('_cke_bookmark')){Z=Z.getNextSourceNode(true);continue;}if(!ad||V[ad]&&(Z.getPosition(Y)|4|0|8)==4+0+8&&(!T.childRule||T.childRule(Z))){var ae=Z.getParent();if(ae&&((ae.getDtd()||f.span)[S]||U)&&(!T.parentRule||T.parentRule(ae))){if(!aa&&(!ad||!f.$removeEmpty[ad]||(Z.getPosition(Y)|4|0|8)==4+0+8)){aa=new d.range(Q);aa.setStartBefore(Z);}if(ac==3||ac==1&&!Z.getChildCount()){var af=Z,ag;while(!af.$.nextSibling&&(ag=af.getParent(),V[ag.getName()])&&(ag.getPosition(X)|2|0|8)==2+0+8&&(!T.childRule||T.childRule(ag)))af=ag;aa.setEndAfter(af);if(!af.$.nextSibling)ab=true;}}else ab=true;}else ab=true;Z=Z.getNextSourceNode();}if(ab&&aa&&!aa.collapsed){var ah=E(al,Q),ai=aa.getCommonAncestor();while(ah&&ai){if(ai.getName()==S){for(var aj in T.attributes){if(ah.getAttribute(aj)==ai.getAttribute(aj))ah.removeAttribute(aj);}for(var ak in T.styles){if(ah.getStyle(ak)==ai.getStyle(ak))ah.removeStyle(ak);}if(!ah.hasAttributes()){ah=null;break;}}ai=ai.getParent();}if(ah){aa.extractContents().appendTo(ah);B(al,ah);aa.insertNode(ah);ah.mergeSiblings();if(!c)ah.$.normalize();}aa=null;}}P.moveToBookmark(W);P.shrink(2);};function p(P){P.enlarge(1); +var Q=P.createBookmark(),R=Q.startNode;if(P.collapsed){var S=new d.elementPath(R.getParent()),T;for(var U=0,V;U'+R+'';else P.setHtml(R);Q.remove();};function w(P){var Q=/(\S\s*)\n(?:\s|(]+_cke_bookmark.*?\/span>))*\n(?!$)/gi,R=P.getName(),S=x(P.getOuterHtml(),Q,function(U,V,W){return V+''+W+'
    ';
    +}),T=[];S.replace(/([\s\S]*?)<\/pre>/gi,function(U,V){T.push(V);});return T;};function x(P,Q,R){var S='',T='';P=P.replace(/(^]+_cke_bookmark.*?\/span>)|(]+_cke_bookmark.*?\/span>$)/gi,function(U,V,W){V&&(S=V);W&&(T=W);return '';});return S+P.replace(Q,R)+T;};function y(P,Q){var R=new d.documentFragment(Q.getDocument());for(var S=0;S');T=T.replace(/[ \t]{2,}/g,function(V){return e.repeat(' ',V.length-1)+' ';});var U=Q.clone();U.setHtml(T);R.append(U);}return R;};function z(P,Q){var R=P.getHtml();R=x(R,/(?:^[ \t\n\r]+)|(?:[ \t\n\r]+$)/g,'');R=R.replace(/[ \t\r\n]*(]*>)[ \t\r\n]*/gi,'$1');R=R.replace(/([ \t\n\r]+| )/g,' ');R=R.replace(/]*>/gi,'\n');if(c){var S=P.getDocument().createElement('div');S.append(Q);Q.$.outerHTML='
    '+R+'
    ';Q=S.getFirst().remove();}else Q.setHtml(R);return Q;};function A(P,Q){var R=P._.definition,S=e.extend({},R.attributes,J(P)[Q.getName()]),T=R.styles,U=e.isEmpty(S)&&e.isEmpty(T);for(var V in S){if((V=='class'||P._.definition.fullMatch)&&Q.getAttribute(V)!=K(V,S[V]))continue;U=Q.hasAttribute(V);Q.removeAttribute(V);}for(var W in T){if(P._.definition.fullMatch&&Q.getStyle(W)!=K(W,T[W],true))continue;U=U||!!Q.getStyle(W);Q.removeStyle(W);}U&&D(Q);};function B(P,Q){var R=P._.definition,S=R.attributes,T=R.styles,U=J(P),V=Q.getElementsByTag(P.element);for(var W=V.count();--W>=0;)A(P,V.getItem(W));for(var X in U){if(X!=P.element){V=Q.getElementsByTag(X);for(W=V.count()-1;W>=0;W--){var Y=V.getItem(W);C(Y,U[X]);}}}};function C(P,Q){var R=Q&&Q.attributes;if(R)for(var S=0;S0)G+=(E.$.offsetWidth||0)-(E.$.clientWidth||0);G+=4;E.setStyle('width',G+'px');u.element.addClass('cke_frameLoaded');var H=u.element.$.scrollHeight;if(c&&b.quirks&&H>0)H+=(E.$.offsetHeight||0)-(E.$.clientHeight||0);E.setStyle('height',H+'px');t._.currentBlock.element.setStyle('display','none').removeStyle('display');}else E.removeStyle('height');var I=t.element,J=I.getWindow(),K=J.getScrollPosition(),L=J.getViewPaneSize(),M={height:I.$.offsetHeight,width:I.$.offsetWidth};if(z?A<0:A+M.width>L.width+K.x)A+=M.width*(z?1:-1);if(B+M.height>L.height+K.y)B-=M.height;if(c){var N=new h(v.$.offsetParent),O=N;if(O.getName()=='html')O=O.getDocument().getBody();if(O.getComputedStyle('direction')=='rtl')if(b.ie8Compat)A-=v.getDocument().getDocumentElement().$.scrollLeft*2;else A-=N.$.scrollWidth-N.$.clientWidth;}v.setStyles({top:B+'px',left:A+'px'});v.setOpacity(1);},this);t.isLoaded?D():t.onLoad=D;e.setTimeout(function(){w.$.contentWindow.focus();this.allowBlur(true);},0,this);},0,this);this.visible=1;if(this.onShow)this.onShow.call(this);m=false;},hide:function(){var o=this;if(o.visible&&(!o.onHide||o.onHide.call(o)!==true)){o.hideChild(); +o.element.setStyle('display','none');o.visible=0;}},allowBlur:function(o){var p=this._.panel;if(o!=undefined)p.allowBlur=o;return p.allowBlur;},showAsChild:function(o,p,q,r,s,t){if(this._.activeChild==o&&o._.panel._.offsetParentId==q.getId())return;this.hideChild();o.onHide=e.bind(function(){e.setTimeout(function(){if(!this._.focused)this.hide();},0,this);},this);this._.activeChild=o;this._.focused=false;o.showBlock(p,q,r,s,t);if(b.ie7Compat||b.ie8&&b.ie6Compat)setTimeout(function(){o.element.getChild(0).$.style.cssText+='';},100);},hideChild:function(){var o=this._.activeChild;if(o){delete o.onHide;delete this._.activeChild;o.hide();}}}});a.on('instanceDestroyed',function(){var o=e.isEmpty(a.instances);for(var p in l){var q=l[p];if(o)q.destroy();else q.element.hide();}o&&(l={});});})();j.add('menu',{beforeInit:function(l){var m=l.config.menu_groups.split(','),n=l._.menuGroups={},o=l._.menuItems={};for(var p=0;p'],A=q.length,B=A&&q[0].group;for(var C=0;C');B=D.group;}D.render(this,C,z);}z.push('');t.setHtml(z.join(''));if(this.parent)this.parent._.panel.showAsChild(s,this.id,m,n,o,p);else s.showBlock(this.id,m,n,o,p);r.fire('menuShow',[s]);},hide:function(){this._.panel&&this._.panel.hide();}}});function l(m){m.sort(function(n,o){if(n.groupo.group)return 1;return n.ordero.order?1:0;});};})();a.menuItem=e.createClass({$:function(l,m,n){var o=this;e.extend(o,n,{order:0,className:'cke_button_'+m});o.group=l._.menuGroups[o.group];o.editor=l;o.name=m;},proto:{render:function(l,m,n){var u=this;var o=l.id+String(m),p=typeof u.state=='undefined'?2:u.state,q=' cke_'+(p==1?'on':p==0?'disabled':'off'),r=u.label;if(u.className)q+=' '+u.className;var s=u.getItems;n.push(''+''); +if(s)n.push('','&#',u.editor.lang.dir=='rtl'?'9668':'9658',';','');n.push(r,'');}}});i.menu_subMenuDelay=400;i.menu_groups='clipboard,form,tablecell,tablecellproperties,tablerow,tablecolumn,table,anchor,link,image,flash,checkbox,radio,textfield,hiddenfield,imagebutton,button,select,textarea,div';(function(){var l=function(n,o){return n._.modes&&n._.modes[o||n.mode];},m;j.add('editingblock',{init:function(n){if(!n.config.editingBlock)return;n.on('themeSpace',function(o){if(o.data.space=='contents')o.data.html+='
    ';});n.on('themeLoaded',function(){n.fireOnce('editingBlockReady');});n.on('uiReady',function(){n.setMode(n.config.startupMode);});n.on('afterSetData',function(){if(!m){function o(){m=true;l(n).loadData(n.getData());m=false;};if(n.mode)o();else n.on('mode',function(){o();n.removeListener('mode',arguments.callee);});}});n.on('beforeGetData',function(){if(!m&&n.mode){m=true;n.setData(l(n).getData());m=false;}});n.on('getSnapshot',function(o){if(n.mode)o.data=l(n).getSnapshotData();});n.on('loadSnapshot',function(o){if(n.mode)l(n).loadSnapshotData(o.data);});n.on('mode',function(o){o.removeListener();b.webkit&&n.container.on('focus',function(){n.focus();});if(n.config.startupFocus)n.focus();setTimeout(function(){n.fireOnce('instanceReady');a.fire('instanceReady',null,n);},0);});}});a.editor.prototype.mode='';a.editor.prototype.addMode=function(n,o){o.name=n;(this._.modes||(this._.modes={}))[n]=o;};a.editor.prototype.setMode=function(n){var o,p=this.getThemeSpace('contents'),q=this.checkDirty();if(this.mode){if(n==this.mode)return;this.fire('beforeModeUnload');var r=l(this);o=r.getData();r.unload(p);this.mode='';}p.setHtml('');var s=l(this,n);if(!s)throw '[CKEDITOR.editor.setMode] Unknown mode "'+n+'".';if(!q)this.on('mode',function(){this.resetDirty();this.removeListener('mode',arguments.callee);});s.load(p,typeof o!='string'?this.getData():o);};a.editor.prototype.focus=function(){var n=l(this);if(n)n.focus();};})();i.startupMode='wysiwyg';i.startupFocus=false;i.editingBlock=true;(function(){function l(){var v=this;try{var s=v.getSelection();if(!s||!s.document.getWindow().$)return;var t=s.getStartElement(),u=new d.elementPath(t);if(!u.compare(v._.selectionPreviousPath)){v._.selectionPreviousPath=u;v.fire('selectionChange',{selection:s,path:u,element:t});}}catch(w){}};var m,n;function o(){n=true;if(m)return;p.call(this);m=e.setTimeout(p,200,this);};function p(){m=null;if(n){e.setTimeout(l,0,this); +n=false;}};var q={modes:{wysiwyg:1,source:1},exec:function(s){switch(s.mode){case 'wysiwyg':s.document.$.execCommand('SelectAll',false,null);break;case 'source':var t=s.textarea.$;if(c)t.createTextRange().execCommand('SelectAll');else{t.selectionStart=0;t.selectionEnd=t.value.length;}t.focus();}},canUndo:false};j.add('selection',{init:function(s){s.on('contentDom',function(){var t=s.document,u=t.getBody(),v=t.getDocumentElement();if(c){var w,x,y=1;u.on('focusin',function(C){if(C.data.$.srcElement.nodeName!='BODY')return;if(w){if(y)try{w.select();}catch(D){}w=null;}});u.on('focus',function(){x=true;B();});u.on('beforedeactivate',function(C){if(C.data.$.toElement)return;x=false;y=1;});if(c&&b.version<8)s.on('blur',function(C){s.document&&s.document.$.selection.empty();});v.on('mousedown',function(){y=0;});v.on('mouseup',function(){y=1;});if(c&&(b.ie7Compat||b.version<8||b.quirks))v.on('click',function(C){if(C.data.getTarget().getName()=='html')s.getSelection().getRanges()[0].select();});var z;u.on('mousedown',function(C){if(C.data.$.button==2){var D=s.document.$.selection;if(D.type=='None')z=s.window.getScrollPosition();}A();});u.on('mouseup',function(C){if(C.data.$.button==2&&z){s.document.$.documentElement.scrollLeft=z.x;s.document.$.documentElement.scrollTop=z.y;}z=null;x=true;setTimeout(function(){B(true);},0);});u.on('keydown',A);u.on('keyup',function(){x=true;B();});t.on('selectionchange',B);function A(){x=false;};function B(C){if(x){var D=s.document,E=s.getSelection(),F=E&&E.getNative();if(C&&F&&F.type=='None')if(!D.$.queryCommandEnabled('InsertImage')){e.setTimeout(B,50,this,true);return;}var G;if(F&&F.type&&F.type!='Control'&&(G=F.createRange())&&(G=G.parentElement())&&(G=G.nodeName)&&G.toLowerCase() in {input:1,textarea:1})return;w=F&&E.getRanges()[0];o.call(s);}};}else{t.on('mouseup',o,s);t.on('keyup',o,s);}});s.addCommand('selectAll',q);s.ui.addButton('SelectAll',{label:s.lang.selectAll,command:'selectAll'});s.selectionChange=o;}});a.editor.prototype.getSelection=function(){return this.document&&this.document.getSelection();};a.editor.prototype.forceNextSelectionCheck=function(){delete this._.selectionPreviousPath;};g.prototype.getSelection=function(){var s=new d.selection(this);return!s||s.isInvalid?null:s;};a.SELECTION_NONE=1;a.SELECTION_TEXT=2;a.SELECTION_ELEMENT=3;d.selection=function(s){var v=this;var t=s.getCustomData('cke_locked_selection');if(t)return t;v.document=s;v.isLocked=false;v._={cache:{}};if(c){var u=v.getNative().createRange();if(!u||u.item&&u.item(0).ownerDocument!=v.document.$||u.parentElement&&u.parentElement().ownerDocument!=v.document.$)v.isInvalid=true; +}return v;};var r={img:1,hr:1,li:1,table:1,tr:1,td:1,th:1,embed:1,object:1,ol:1,ul:1,a:1,input:1,form:1,select:1,textarea:1,button:1,fieldset:1,th:1,thead:1,tfoot:1};d.selection.prototype={getNative:c?function(){return this._.cache.nativeSel||(this._.cache.nativeSel=this.document.$.selection);}:function(){return this._.cache.nativeSel||(this._.cache.nativeSel=this.document.getWindow().$.getSelection());},getType:c?function(){var s=this._.cache;if(s.type)return s.type;var t=1;try{var u=this.getNative(),v=u.type;if(v=='Text')t=2;if(v=='Control')t=3;if(u.createRange().parentElement)t=2;}catch(w){}return s.type=t;}:function(){var s=this._.cache;if(s.type)return s.type;var t=2,u=this.getNative();if(!u)t=1;else if(u.rangeCount==1){var v=u.getRangeAt(0),w=v.startContainer;if(w==v.endContainer&&w.nodeType==1&&v.endOffset-v.startOffset==1&&r[w.childNodes[v.startOffset].nodeName.toLowerCase()])t=3;}return s.type=t;},getRanges:(function(){var s=c?(function(){var t=function(u,v){u=u.duplicate();u.collapse(v);var w=u.parentElement(),x=w.childNodes,y;for(var z=0;z0)break;else if(!B||C==1&&B==-1)return{container:w,offset:z};else if(!C)return{container:w,offset:z+1};y=null;}}if(!y){y=u.duplicate();y.moveToElementText(w);y.collapse(false);}y.setEndPoint('StartToStart',u);var D=y.text.replace(/(\r\n|\r)/g,'\n').length;try{while(D>0)D-=x[--z].nodeValue.length;}catch(E){D=0;}if(D===0)return{container:w,offset:z};else return{container:x[z],offset:-D};};return function(){var E=this;var u=E.getNative(),v=u&&u.createRange(),w=E.getType(),x;if(!u)return[];if(w==2){x=new d.range(E.document);var y=t(v,true);x.setStart(new d.node(y.container),y.offset);y=t(v);x.setEnd(new d.node(y.container),y.offset);return[x];}else if(w==3){var z=[];for(var A=0;A=z.getLength())D.setStartAfter(z);else D.setStartBefore(z);if(A&&A.type==3)if(!C)D.setEndBefore(A);else D.setEndAfter(A);var F=new d.walker(D);F.evaluator=function(G){if(G.type==1&&G.getAttribute('contenteditable')=='false'){var H=x.clone();x.setEndBefore(G);if(x.collapsed)v.splice(w--,1);if(!(G.getPosition(D.endContainer)&16)){H.setStartAfter(G);if(!H.collapsed)v.splice(w+1,0,H);}return true;}return false;};F.next();}}return u.ranges;};})(),getStartElement:function(){var z=this;var s=z._.cache;if(s.startElement!==undefined)return s.startElement;var t,u=z.getNative();switch(z.getType()){case 3:return z.getSelectedElement();case 2:var v=z.getRanges()[0];if(v)if(!v.collapsed){v.optimize();for(;;){var w=v.startContainer,x=v.startOffset;if(x==(w.getChildCount?w.getChildCount():w.getLength())&&!w.isBlockBoundary())v.setStartAfter(w);else break;}t=v.startContainer;if(t.type!=1)return t.getParent();t=t.getChild(v.startOffset);if(!t||t.type!=1)return v.startContainer;var y=t.getFirst();while(y&&y.type==1){t=y;y=y.getFirst();}return t;}if(c){v=u.createRange();v.collapse(true);t=v.parentElement();}else{t=u.anchorNode;if(t&&t.nodeType!=1)t=t.parentNode;}}return s.startElement=t?new h(t):null;},getSelectedElement:function(){var s=this._.cache;if(s.selectedElement!==undefined)return s.selectedElement;var t=this,u=e.tryThese(function(){return t.getNative().createRange().item(0);},function(){var v=t.getRanges()[0],w,x;for(var y=2;y&&!((w=v.getEnclosedNode())&&w.type==1&&r[w.getName()]&&(x=w));y--)v.shrink(1);return x.$;});return s.selectedElement=u?new h(u):null;},lock:function(){var s=this;s.getRanges();s.getStartElement();s.getSelectedElement();s._.cache.nativeSel={};s.isLocked=true;s.document.setCustomData('cke_locked_selection',s);},unlock:function(s){var x=this;var t=x.document,u=t.getCustomData('cke_locked_selection');if(u){t.setCustomData('cke_locked_selection',null);if(s){var v=u.getSelectedElement(),w=!v&&u.getRanges();x.isLocked=false;x.reset();t.getBody().focus();if(v)x.selectElement(v);else x.selectRanges(w);}}if(!u||!s){x.isLocked=false;x.reset();}},reset:function(){this._.cache={}; +},selectElement:function(s){var v=this;if(v.isLocked){var t=new d.range(v.document);t.setStartBefore(s);t.setEndAfter(s);v._.cache.selectedElement=s;v._.cache.startElement=s;v._.cache.ranges=new d.rangeList(t);v._.cache.type=3;return;}if(c){v.getNative().empty();try{t=v.document.$.body.createControlRange();t.addElement(s.$);t.select();}catch(w){t=v.document.$.body.createTextRange();t.moveToElementText(s.$);t.select();}finally{v.document.fire('selectionchange');}v.reset();}else{t=v.document.$.createRange();t.selectNode(s.$);var u=v.getNative();u.removeAllRanges();u.addRange(t);v.reset();}},selectRanges:function(s){var C=this;if(C.isLocked){C._.cache.selectedElement=null;C._.cache.startElement=s[0]&&s[0].getTouchedStartNode();C._.cache.ranges=new d.rangeList(s);C._.cache.type=2;return;}if(c){if(s.length>1){var t=s[s.length-1];s[0].setEnd(t.endContainer,t.endOffset);s.length=1;}if(s[0])s[0].select();C.reset();}else{var u=C.getNative();if(s.length)u.removeAllRanges();for(var v=0;v=0){r.collapse(true);p.setEnd(r.endContainer.$,r.endOffset);}else throw s;}var q=r.document.getSelection().getNative();q.removeAllRanges();q.addRange(p);};})();(function(){var l={elements:{$:function(m){var n=m.attributes,o=n&&n._cke_realelement,p=o&&new a.htmlParser.fragment.fromHtml(decodeURIComponent(o)),q=p&&p.children[0];if(q&&m.attributes._cke_resizable){var r=m.attributes.style;if(r){var s=/(?:^|\s)width\s*:\s*(\d+)/i.exec(r),t=s&&s[1];s=/(?:^|\s)height\s*:\s*(\d+)/i.exec(r);var u=s&&s[1];if(t)q.attributes.width=t;if(u)q.attributes.height=u;}}return q;}}};j.add('fakeobjects',{requires:['htmlwriter'],afterInit:function(m){var n=m.dataProcessor,o=n&&n.htmlFilter;if(o)o.addRules(l);}});})();a.editor.prototype.createFakeElement=function(l,m,n,o){var p=this.lang.fakeobjects,q={'class':m,src:a.getUrl('images/spacer.gif'),_cke_realelement:encodeURIComponent(l.getOuterHtml()),_cke_real_node_type:l.type,alt:p[n]||p.unknown,align:l.getAttribute('align')||''};if(n)q._cke_real_element_type=n;if(o)q._cke_resizable=o;return this.document.createElement('img',{attributes:q});};a.editor.prototype.createFakeParserElement=function(l,m,n,o){var p=this.lang.fakeobjects,q,r=new a.htmlParser.basicWriter();l.writeHtml(r);q=r.getHtml();var s={'class':m,src:a.getUrl('images/spacer.gif'),_cke_realelement:encodeURIComponent(q),_cke_real_node_type:l.type,alt:p[n]||p.unknown,align:l.attributes.align||''};if(n)s._cke_real_element_type=n;if(o)s._cke_resizable=o;return new a.htmlParser.element('img',s);};a.editor.prototype.restoreRealElement=function(l){if(l.getAttribute('_cke_real_node_type')!=1)return null; +return h.createFromHtml(decodeURIComponent(l.getAttribute('_cke_realelement')),this.document);};j.add('richcombo',{requires:['floatpanel','listblock','button'],beforeInit:function(l){l.ui.addHandler(3,k.richCombo.handler);}});a.UI_RICHCOMBO=3;k.richCombo=e.createClass({$:function(l){var n=this;e.extend(n,l,{title:l.label,modes:{wysiwyg:1}});var m=n.panel||{};delete n.panel;n.id=e.getNextNumber();n.document=m&&m.parent&&m.parent.getDocument()||a.document;m.className=(m.className||'')+' cke_rcombopanel';m.block={multiSelect:m.multiSelect,attributes:m.attributes};n._={panelDefinition:m,items:{},state:2};},statics:{handler:{create:function(l){return new k.richCombo(l);}}},proto:{renderHtml:function(l){var m=[];this.render(l,m);return m.join('');},render:function(l,m){var n=b,o='cke_'+this.id,p=e.addFunction(function(s){var v=this;var t=v._;if(t.state==0)return;v.createPanel(l);if(t.on){t.panel.hide();return;}if(!t.committed){t.list.commit();t.committed=1;}var u=v.getValue();if(u)t.list.mark(u);else t.list.unmarkAll();t.panel.showBlock(v.id,new h(s),4);},this),q={id:o,combo:this,focus:function(){var s=a.document.getById(o).getChild(1);s.focus();},clickFn:p};l.on('mode',function(){this.setState(this.modes[l.mode]?2:0);},this);var r=e.addFunction(function(s,t){s=new d.event(s);var u=s.getKeystroke();switch(u){case 13:case 32:case 40:e.callFunction(p,t);break;default:q.onkey(q,u);}s.preventDefault();});q.keyDownFn=r;m.push('','','',this.label,'','=10900&&!n.hc?'':" href=\"javascript:void('"+this.label+"')\"",' role="button" aria-labelledby="',o,'_label" aria-describedby="',o,'_text" aria-haspopup="true"');if(b.opera||b.gecko&&b.mac)m.push(' onkeypress="return false;"');if(b.gecko)m.push(' onblur="this.style.cssText = this.style.cssText;"');m.push(' onkeydown="CKEDITOR.tools.callFunction( ',r,', event, this );" onclick="CKEDITOR.tools.callFunction(',p,', this); return false;">'+this.label+''+''+''+(b.hc?'':'')+''+''+''+'');if(this.onRender)this.onRender();return q;},createPanel:function(l){if(this._.panel)return;var m=this._.panelDefinition,n=this._.panelDefinition.block,o=m.parent||a.document.getBody(),p=new k.floatPanel(l,o,m),q=p.addListBlock(this.id,n),r=this; +p.onShow=function(){if(r.className)this.element.getFirst().addClass(r.className+'_panel');r.setState(1);q.focus(!r.multiSelect&&r.getValue());r._.on=1;if(r.onOpen)r.onOpen();};p.onHide=function(){if(r.className)this.element.getFirst().removeClass(r.className+'_panel');r.setState(2);r._.on=0;if(r.onClose)r.onClose();};p.onEscape=function(){p.hide();r.document.getById('cke_'+r.id).getFirst().getNext().focus();};q.onClick=function(s,t){r.document.getWindow().focus();if(r.onClick)r.onClick.call(r,s,t);if(t)r.setValue(s,r._.items[s]);else r.setValue('');p.hide();};this._.panel=p;this._.list=q;p.getBlock(this.id).onHide=function(){r._.on=0;r.setState(2);};if(this.init)this.init();},setValue:function(l,m){var o=this;o._.value=l;var n=o.document.getById('cke_'+o.id+'_text');if(!(l||m)){m=o.label;n.addClass('cke_inline_label');}else n.removeClass('cke_inline_label');n.setHtml(typeof m!='undefined'?m:l);},getValue:function(){return this._.value||'';},unmarkAll:function(){this._.list.unmarkAll();},mark:function(l){this._.list.mark(l);},hideItem:function(l){this._.list.hideItem(l);},hideGroup:function(l){this._.list.hideGroup(l);},showAll:function(){this._.list.showAll();},add:function(l,m,n){this._.items[l]=n||l;this._.list.add(l,m,n);},startGroup:function(l){this._.list.startGroup(l);},commit:function(){this._.list.commit();},setState:function(l){var m=this;if(m._.state==l)return;m.document.getById('cke_'+m.id).setState(l);m._.state=l;}}});k.prototype.addRichCombo=function(l,m){this.add(l,3,m);};j.add('htmlwriter');a.htmlWriter=e.createClass({base:a.htmlParser.basicWriter,$:function(){var n=this;n.base();n.indentationChars='\t';n.selfClosingEnd=' />';n.lineBreakChars='\n';n.forceSimpleAmpersand=false;n.sortAttributes=true;n._.indent=false;n._.indentation='';n._.rules={};var l=f;for(var m in e.extend({},l.$nonBodyContent,l.$block,l.$listItem,l.$tableContent))n.setRules(m,{indent:true,breakBeforeOpen:true,breakAfterOpen:true,breakBeforeClose:!l[m]['#'],breakAfterClose:true});n.setRules('br',{breakAfterOpen:true});n.setRules('title',{indent:false,breakAfterOpen:false});n.setRules('style',{indent:false,breakBeforeClose:true});n.setRules('pre',{indent:false});},proto:{openTag:function(l,m){var o=this;var n=o._.rules[l];if(o._.indent)o.indentation();else if(n&&n.breakBeforeOpen){o.lineBreak();o.indentation();}o._.output.push('<',l);},openTagClose:function(l,m){var o=this;var n=o._.rules[l];if(m)o._.output.push(o.selfClosingEnd);else{o._.output.push('>');if(n&&n.indent)o._.indentation+=o.indentationChars; +}if(n&&n.breakAfterOpen)o.lineBreak();},attribute:function(l,m){if(typeof m=='string'){this.forceSimpleAmpersand&&(m=m.replace(/&/g,'&'));m=e.htmlEncodeAttr(m);}this._.output.push(' ',l,'="',m,'"');},closeTag:function(l){var n=this;var m=n._.rules[l];if(m&&m.indent)n._.indentation=n._.indentation.substr(n.indentationChars.length);if(n._.indent)n.indentation();else if(m&&m.breakBeforeClose){n.lineBreak();n.indentation();}n._.output.push('');if(m&&m.breakAfterClose)n.lineBreak();},text:function(l){if(this._.indent){this.indentation();l=e.ltrim(l);}this._.output.push(l);},comment:function(l){if(this._.indent)this.indentation();this._.output.push('');},lineBreak:function(){var l=this;if(l._.output.length>0)l._.output.push(l.lineBreakChars);l._.indent=true;},indentation:function(){this._.output.push(this._.indentation);this._.indent=false;},setRules:function(l,m){var n=this._.rules[l];if(n)e.extend(n,m,true);else this._.rules[l]=m;}}});j.add('menubutton',{requires:['button','contextmenu'],beforeInit:function(l){l.ui.addHandler(5,k.menuButton.handler);}});a.UI_MENUBUTTON=5;(function(){var l=function(m){var n=this._;if(n.state===0)return;n.previousState=n.state;var o=n.menu;if(!o){o=n.menu=new j.contextMenu(m);o.definition.panel.attributes['aria-label']=m.lang.common.options;o.onHide=e.bind(function(){this.setState(n.previousState);},this);if(this.onMenu)o.addListener(this.onMenu);}if(n.on){o.hide();return;}this.setState(1);o.show(a.document.getById(this._.id),4);};k.menuButton=e.createClass({base:k.button,$:function(m){var n=m.panel;delete m.panel;this.base(m);this.hasArrow=true;this.click=l;},statics:{handler:{create:function(m){return new k.menuButton(m);}}}});})();j.add('dialogui');(function(){var l=function(t){var w=this;w._||(w._={});w._['default']=w._.initValue=t['default']||'';w._.required=t.required||false;var u=[w._];for(var v=1;v',u.label,'','');else{var C={type:'hbox',widths:u.widths,padding:0,children:[{type:'html',html:'