[Bps-public-commit] rt-extension-mobileui branch, master, created. 23b6ba001b09a7e45f067b523a1fcec190ae6538
Jesse Vincent
jesse at bestpractical.com
Wed Jul 14 18:51:55 EDT 2010
The branch, master has been created
at 23b6ba001b09a7e45f067b523a1fcec190ae6538 (commit)
- Log -----------------------------------------------------------------
commit 9832f64e9fc3daf8f86f5376c92644fce27ebb68
Author: Jesse Vincent <jesse at bestpractical.com>
Date: Tue Jul 13 10:12:36 2010 +0200
Initial import of ongoing work
diff --git a/html/Callbacks/RT-Extension-MobileUI/Elements/Login/Header b/html/Callbacks/RT-Extension-MobileUI/Elements/Login/Header
new file mode 100644
index 0000000..43f0b23
--- /dev/null
+++ b/html/Callbacks/RT-Extension-MobileUI/Elements/Login/Header
@@ -0,0 +1,5 @@
+<%init>
+return unless ($m->request_comp->path() =~ m{^/m(?:\/|$)});
+$m->comp('/m/login',%ARGS);
+$m->abort;
+</%init>
diff --git a/html/Callbacks/RT-Extension-MobileUI/index.html/Initial b/html/Callbacks/RT-Extension-MobileUI/index.html/Initial
new file mode 100644
index 0000000..39df5e8
--- /dev/null
+++ b/html/Callbacks/RT-Extension-MobileUI/index.html/Initial
@@ -0,0 +1,5 @@
+<%init>
+if (($ENV{'HTTP_USER_AGENT'} || '') !~ /(?:hiptop|Blazer|Novarra|Vagabond|SonyEricsson|Symbian|NetFront|UP.Browser|UP.Link|Windows CE|MIDP|J2ME|DoCoMo|J-PHONE|PalmOS|PalmSource|iPhone|iPod|AvantGo|Nokia|Android)/io && !$session{'NotMobile'}) {
+ RT::Interface::Web::Redirect('/m');
+}
+</%init>
diff --git a/html/m/_elements/footer b/html/m/_elements/footer
new file mode 100644
index 0000000..308b1d0
--- /dev/null
+++ b/html/m/_elements/footer
@@ -0,0 +1,2 @@
+</body>
+</html>
diff --git a/html/m/_elements/header b/html/m/_elements/header
new file mode 100644
index 0000000..678b075
--- /dev/null
+++ b/html/m/_elements/header
@@ -0,0 +1,2 @@
+<html>
+<body>
diff --git a/html/m/_elements/menu b/html/m/_elements/menu
new file mode 100644
index 0000000..34cb93d
--- /dev/null
+++ b/html/m/_elements/menu
@@ -0,0 +1,30 @@
+<ul class="menu">
+% for my $item (@menu) {
+<li><a href="<%$item->{url}%>"><%$item->{label}%></li>
+% }
+</ul>
+<%init>
+my @menu = (
+{ label => loc("My tickets"),
+ url => '/m/tickets/owned'
+},
+ {
+ label => loc("My requests"),
+ url => '/m/tickets/requested'
+ },
+ {
+ label => loc("All tickets"),
+ url => '/m/tickets/all'
+ },
+{
+ label => loc("New ticket"),
+ url => '/m/ticket/create',
+},
+{
+ label => loc("Logout"),
+ url => '/m/logout',
+}
+
+
+);
+</%init>
diff --git a/html/m/_elements/ticket_list b/html/m/_elements/ticket_list
new file mode 100644
index 0000000..2cc6594
--- /dev/null
+++ b/html/m/_elements/ticket_list
@@ -0,0 +1,18 @@
+<%args>
+$query => ''
+$page => ''
+</%args>
+<%init>
+</%init>
+<&| /m/_elements/wrapper &>
+<& /Elements/CollectionList,
+ Query => $query,
+ OrderBy => 'id',
+ Order => 'desc',
+ Rows => '25',
+ Page => $page,
+ Format => q{'<a href="__WebPath__/m/ticket/show?id=__id__">__id__</a>','<a href="__WebPath__/m/ticket/show?id=__id__">Subject</a>',Status,Requestors,Owner,Priority},
+ Class => 'RT::Tickets',
+ BaseURL => '/m/list/'
+&>
+</&>
diff --git a/html/m/_elements/wrapper b/html/m/_elements/wrapper
new file mode 100644
index 0000000..f0da9e3
--- /dev/null
+++ b/html/m/_elements/wrapper
@@ -0,0 +1,6 @@
+<%init>
+$m->comp('header');
+$m->out($m->content);
+$m->comp('footer');
+$m->abort();
+</%init>
diff --git a/html/m/dhandler b/html/m/dhandler
new file mode 100644
index 0000000..d5d9dd1
--- /dev/null
+++ b/html/m/dhandler
@@ -0,0 +1,6 @@
+%# %$HTML::Mason::Commands::r->status(404);
+%# fix this sometime
+<&| _elements/wrapper &>
+<h1><%loc("Page not found")%></h1>
+<& _elements/menu &>
+</&>
diff --git a/html/m/index.html b/html/m/index.html
new file mode 100644
index 0000000..6ca1217
--- /dev/null
+++ b/html/m/index.html
@@ -0,0 +1,4 @@
+<&| _elements/wrapper &>
+<%loc("RT for [_1]",RT->Config->Get('rtname'))%>
+<& _elements/menu &>
+</&>
diff --git a/html/m/login b/html/m/login
new file mode 100644
index 0000000..aed5393
--- /dev/null
+++ b/html/m/login
@@ -0,0 +1,82 @@
+<%INIT>
+my $req_uri;
+
+if (UNIVERSAL::can($r, 'uri') and $r->uri =~ m{.*/(.*)}) {
+ $req_uri = $1;
+}
+
+my $form_action = defined $goto ? $goto
+ : defined $req_uri ? $req_uri
+ : RT->Config->Get('WebPath')
+ ;
+
+# sanitize $form_action
+my $uri = URI->new($form_action);
+
+# You get undef scheme with a relative uri like "/Search/Build.html"
+unless (!defined($uri->scheme) || $uri->scheme eq 'http' || $uri->scheme eq 'https') {
+ $form_action = RT->Config->Get('WebPath');
+}
+
+# Make sure we're logging in to the same domain
+# You can get an undef authority with a relative uri like "index.html"
+my $uri_base_url = URI->new(RT->Config->Get('WebBaseURL'));
+unless (!defined($uri->authority) || $uri->authority eq $uri_base_url->authority) {
+ $form_action = RT->Config->Get('WebPath');
+}
+</%INIT>
+<&| /m/_elements/wrapper &>
+
+
+<div id="body" class="login-body">
+% if ($Error) {
+<&| "/Widgets/TitleBox", title => loc('Error'), hideable => 0, class => 'error' &>
+<% $Error %>
+</&>
+% }
+
+
+<div id="login-box">
+<&| /Widgets/TitleBox, title => loc('Login'), titleright => $RT::VERSION, hideable => 0 &>
+
+% unless (RT->Config->Get('WebExternalAuth') and !RT->Config->Get('WebFallbackToInternalAuth')) {
+<form id="login" name="login" method="post" action="<% $form_action %>">
+
+<div class="input-row">
+ <span class="label"><&|/l&>Username</&>:</span>
+ <span class="input"><input name="user" value="<%$user%>" id="user" /></span>
+</div>
+
+<div class="input-row">
+ <span class="label"><&|/l&>Password</&>:</span>
+ <span class="input"><input type="password" name="pass" autocomplete="off" /></span>
+</div>
+
+<div class="button-row">
+ <span class="input"><input type="submit" class="button" value="<&|/l&>Login</&>" /></span>
+</div>
+
+% foreach my $key (keys %ARGS) {
+% if (($key ne 'user') and ($key ne 'pass')) {
+% if (ref($ARGS{$key}) =~ /ARRAY/) {
+% foreach my $val (@{$ARGS{$key}}) {
+<input type="hidden" class="hidden" name="<%$key %>" value="<% $val %>" />
+% }
+% }
+% else {
+<input type="hidden" class="hidden" name="<% $key %>" value="<% $ARGS{$key} %>" />
+% }
+% }
+% }
+</form>
+% }
+</&>
+</div><!-- #login-box -->
+</div><!-- #login-body -->
+</&>
+<%ARGS>
+$user => ""
+$pass => undef
+$goto => undef
+$Error => undef
+</%ARGS>
diff --git a/html/m/logout b/html/m/logout
new file mode 100644
index 0000000..ce2e9cc
--- /dev/null
+++ b/html/m/logout
@@ -0,0 +1,8 @@
+<%init>
+if (keys %session) {
+ tied(%session)->delete;
+ $session{'CurrentUser'} = RT::CurrentUser->new;
+}
+RT::Interface::Web::Redirect('/');
+
+</%init>
diff --git a/html/m/ticket/create b/html/m/ticket/create
new file mode 100644
index 0000000..e69de29
diff --git a/html/m/ticket/history b/html/m/ticket/history
new file mode 100644
index 0000000..6dbd3fd
--- /dev/null
+++ b/html/m/ticket/history
@@ -0,0 +1,24 @@
+<%args>
+$id => undef
+</%args>
+<%init>
+my $t = RT::Ticket->new($session{CurrentUser});
+$t->Load($id);
+my $history = $t->Transactions()->ItemsArrayRef;
+</%init>
+<&| /m/_elements/wrapper &>
+<ul>
+% for my $entry (@$history) {
+<li>
+<% $entry->CreatedAsString() %>
+ <& /Elements/ShowUser, User => $entry->CreatorObj &>
+<%$entry->BriefDescription%>
+% if ($entry->Type !~ /EmailRecord/) {
+<div class="txn-content">
+<%$entry->Content%>
+</div>
+% }
+</li>
+% }
+</ul>
+</&>
diff --git a/html/m/ticket/modify b/html/m/ticket/modify
new file mode 100644
index 0000000..e69de29
diff --git a/html/m/ticket/reply b/html/m/ticket/reply
new file mode 100644
index 0000000..e69de29
diff --git a/html/m/ticket/show b/html/m/ticket/show
new file mode 100644
index 0000000..701f52c
--- /dev/null
+++ b/html/m/ticket/show
@@ -0,0 +1,61 @@
+<%args>
+$id => undef
+</%args>
+<%init>
+my $t = RT::Ticket->new($session{CurrentUser});
+$t->Load($id);
+</%init>
+<&| /m/_elements/wrapper &>
+
+
+ <&| /Widgets/TitleBox, title => loc('The Basics'),
+ class => 'ticket-info-basics',
+ &>
+ <& /Ticket/Elements/ShowBasics, Ticket => $t &>
+ </&>
+
+% if ($t->CustomFields->First) {
+ <&| /Widgets/TitleBox, title => loc('Custom Fields'),
+ title_href => RT->Config->Get('WebPath')."/Ticket/Modify.html?id=".$t->Id,
+ class => 'ticket-info-cfs',
+ &>
+ <& /Ticket/Elements/ShowCustomFields, Ticket => $t &>
+ </&>
+% }
+
+ <&| /Widgets/TitleBox, title => loc('People'),
+ class => 'ticket-info-people',
+ &>
+ <& /Ticket/Elements/ShowPeople, Ticket => $t &>
+ </&>
+
+ <& /Ticket/Elements/ShowAttachments, Ticket => $t &>
+
+ <& /Ticket/Elements/ShowRequestor, Ticket => $t &>
+
+% if ( RT->Config->Get('EnableReminders') ) {
+ <&|/Widgets/TitleBox, title => loc("Reminders"),
+ class => 'ticket-info-reminders',
+ &>
+ <table><tr><td>
+ <form action="<%RT->Config->Get('WebPath')%>/Ticket/Display.html" method="post">
+ <& /Ticket/Elements/Reminders, Ticket => $t, ShowCompleted => 0 &>
+ <div align="right"><input type="submit" class="button" value="<&|/l&>Save</&>" /></div>
+ </form>
+ </td></tr></table>
+ </&>
+% }
+
+ <&| /Widgets/TitleBox, title => loc("Dates"),
+ class => 'ticket-info-dates',
+ &>
+ <& /Ticket/Elements/ShowDates, Ticket => $t &>
+ </&>
+
+ <&| /Widgets/TitleBox, title => loc('Links'),
+ class => 'ticket-info-links',
+ &>
+ <& /Elements/ShowLinks, Ticket => $t &>
+ </&>
+
+</&>
diff --git a/html/m/tickets/all b/html/m/tickets/all
new file mode 100644
index 0000000..b17bc29
--- /dev/null
+++ b/html/m/tickets/all
@@ -0,0 +1,4 @@
+<%init>
+ $m->comp('../_elements/ticket_list', %ARGS, query => 'id > 0' );
+$m->abort();
+</%init>
diff --git a/html/m/tickets/owned b/html/m/tickets/owned
new file mode 100644
index 0000000..00d63f4
--- /dev/null
+++ b/html/m/tickets/owned
@@ -0,0 +1,4 @@
+<%init>
+ $m->comp('../_elements/ticket_list', %ARGS, query => 'Owner = "'.$session{CurrentUser}->Name.'" AND (Status != "resolved" AND Status != "rejected" AND Status != "stalled")');
+$m->abort();
+</%init>
diff --git a/html/m/tickets/requested b/html/m/tickets/requested
new file mode 100644
index 0000000..3043e05
--- /dev/null
+++ b/html/m/tickets/requested
@@ -0,0 +1,4 @@
+<%init>
+ $m->comp('../_elements/ticket_list', %ARGS, query => 'Requestors.EmailAddress = "'.$session{CurrentUser}->EmailAddress.'" AND (Status != "resolved" AND Status != "rejected" AND Status != "stalled")');
+$m->abort();
+</%init>
diff --git a/lib/RT/Extension/MobileUI.pm b/lib/RT/Extension/MobileUI.pm
new file mode 100644
index 0000000..332e3d1
--- /dev/null
+++ b/lib/RT/Extension/MobileUI.pm
@@ -0,0 +1,8 @@
+use warnings;
+use strict;
+
+package RT::Extension::MobileUI;
+
+my $VERSION = 1;
+
+1;
commit 23b6ba001b09a7e45f067b523a1fcec190ae6538
Author: Jesse Vincent <jesse at bestpractical.com>
Date: Thu Jul 15 00:50:04 2010 +0200
ticket creation, beginnings of ui
diff --git a/html/m/_elements/header b/html/m/_elements/header
index 678b075..8655c34 100644
--- a/html/m/_elements/header
+++ b/html/m/_elements/header
@@ -1,2 +1,5 @@
<html>
+<head>
+<link rel="stylesheet" type="text/css" href="<%RT->Config->Get('WebPath')|n%>/m/style.css"/>
+</head>
<body>
diff --git a/html/m/_elements/menu b/html/m/_elements/menu
index 34cb93d..9bfb339 100644
--- a/html/m/_elements/menu
+++ b/html/m/_elements/menu
@@ -1,8 +1,10 @@
+<&| /Widgets/TitleBox &>
<ul class="menu">
% for my $item (@menu) {
<li><a href="<%$item->{url}%>"><%$item->{label}%></li>
% }
</ul>
+</&>
<%init>
my @menu = (
{ label => loc("My tickets"),
diff --git a/html/m/_elements/ticket_list b/html/m/_elements/ticket_list
index 2cc6594..c51abbb 100644
--- a/html/m/_elements/ticket_list
+++ b/html/m/_elements/ticket_list
@@ -5,6 +5,7 @@ $page => ''
<%init>
</%init>
<&| /m/_elements/wrapper &>
+<&|/Widgets/TitleBox &>
<& /Elements/CollectionList,
Query => $query,
OrderBy => 'id',
@@ -16,3 +17,4 @@ $page => ''
BaseURL => '/m/list/'
&>
</&>
+</&>
diff --git a/html/m/style.css b/html/m/style.css
new file mode 100644
index 0000000..c5fbc34
--- /dev/null
+++ b/html/m/style.css
@@ -0,0 +1,79 @@
+body {
+ font-family: helvetica, arial, sans-serif;
+ background-color: #ccf;
+ text-rendering: optimizeLegibility;
+}
+
+.titlebox-title {
+ font-size: 1.3em;
+ padding-top: 1em;
+ text-decoration: underline;
+}
+
+ul.menu
+{
+ text-align: left;
+ list-style: none;
+ padding: 0;
+ margin: -0.6em;
+ left: 0;
+}
+
+ul.menu li
+{
+ display: block;
+ margin: 0;
+ padding: 0;
+}
+
+ul.menu li a:active, ul.menu li a:hover {
+ background-color: #eee;
+}
+
+
+ul.menu li a
+{
+ display: block;
+ padding: 1em;
+ margin: 0;
+ border:0;
+ border-top-width: 1px;
+ border-top-color: #666;
+ border-style: solid;
+ text-decoration: none;
+}
+
+ul.menu li:first-child a {
+ border: none;
+}
+
+ul.menu li#active a
+{
+ color: #800000;
+}
+
+div.titlebox {
+ padding: 1em;
+ -moz-border-radius: 1em;
+ -webkit-border-radius: 1em;
+ margin: 1em;
+ background-color: #fff;
+
+}
+
+hr.clear {
+ display: none;
+}
+
+
+.label, .labeltop {
+ text-align: right;
+ display: inline-block;
+ width: 6em;
+}
+
+%$m->abort();
+</%init>
+ $HTML::Mason::Commands::r->content_type('text/css');
+
+</%init>
diff --git a/html/m/ticket/create b/html/m/ticket/create
index e69de29..d9d820b 100644
--- a/html/m/ticket/create
+++ b/html/m/ticket/create
@@ -0,0 +1,395 @@
+<%ARGS>
+$QuoteTransaction => undef
+$CloneTicket => undef
+</%ARGS>
+<%init>
+$m->callback( CallbackName => "Init", ARGSRef => \%ARGS );
+my $Queue = $ARGS{Queue};
+
+
+my $showrows = sub {
+ my @pairs = @_;
+
+ while (@pairs) {
+ my $key = shift @pairs;
+ my $val = shift @pairs;
+
+ $m->out("<div><label>$key</label><div class=\"value\">$val</div></div>");
+
+ }
+
+};
+
+
+my $CloneTicketObj;
+if ($CloneTicket) {
+ $CloneTicketObj = RT::Ticket->new( $session{CurrentUser} );
+ $CloneTicketObj->Load($CloneTicket)
+ or Abort( loc("Ticket could not be loaded") );
+
+ my $clone = {
+ Requestors => join( ',', $CloneTicketObj->RequestorAddresses ),
+ Cc => join( ',', $CloneTicketObj->CcAddresses ),
+ AdminCc => join( ',', $CloneTicketObj->AdminCcAddresses ),
+ InitialPriority => $CloneTicketObj->Priority,
+ };
+
+ $clone->{$_} = $CloneTicketObj->$_()
+ for qw/Owner Subject FinalPriority TimeEstimated TimeWorked
+ Status TimeLeft/;
+
+ $clone->{$_} = $CloneTicketObj->$_->AsString
+ for grep { $CloneTicketObj->$_->Unix }
+ map { $_ . "Obj" } qw/Starts Started Due Resolved/;
+
+ my $members = $CloneTicketObj->Members;
+ my ( @members, @members_of, @refers, @refers_by, @depends, @depends_by );
+ my $refers = $CloneTicketObj->RefersTo;
+ while ( my $refer = $refers->Next ) {
+ push @refers, $refer->LocalTarget;
+ }
+ $clone->{'new-RefersTo'} = join ' ', @refers;
+
+ my $refers_by = $CloneTicketObj->ReferredToBy;
+ while ( my $refer_by = $refers_by->Next ) {
+ push @refers_by, $refer_by->LocalBase;
+ }
+ $clone->{'RefersTo-new'} = join ' ', @refers_by;
+ if (0) { # Temporarily disabled
+ my $depends = $CloneTicketObj->DependsOn;
+ while ( my $depend = $depends->Next ) {
+ push @depends, $depend->LocalTarget;
+ }
+ $clone->{'new-DependsOn'} = join ' ', @depends;
+
+ my $depends_by = $CloneTicketObj->DependedOnBy;
+ while ( my $depend_by = $depends_by->Next ) {
+ push @depends_by, $depend_by->LocalBase;
+ }
+ $clone->{'DependsOn-new'} = join ' ', @depends_by;
+
+ while ( my $member = $members->Next ) {
+ push @members, $member->LocalBase;
+ }
+ $clone->{'MemberOf-new'} = join ' ', @members;
+
+ my $members_of = $CloneTicketObj->MemberOf;
+ while ( my $member_of = $members_of->Next ) {
+ push @members_of, $member_of->LocalTarget;
+ }
+ $clone->{'new-MemberOf'} = join ' ', @members_of;
+
+ }
+
+ my $cfs = $CloneTicketObj->QueueObj->TicketCustomFields();
+ while ( my $cf = $cfs->Next ) {
+ my $cf_id = $cf->id;
+ my $cf_values = $CloneTicketObj->CustomFieldValues( $cf->id );
+ my @cf_values;
+ while ( my $cf_value = $cf_values->Next ) {
+ push @cf_values, $cf_value->Content;
+ }
+ $clone->{"Object-RT::Ticket--CustomField-$cf_id-Value"} = join "\n",
+ @cf_values;
+ }
+
+ for ( keys %$clone ) {
+ $ARGS{$_} = $clone->{$_} if not defined $ARGS{$_};
+ }
+
+}
+
+my @results;
+
+my $title = loc("Create a new ticket");
+
+my $QueueObj = new RT::Queue($session{'CurrentUser'});
+$QueueObj->Load($Queue) || Abort(loc("Queue could not be loaded."));
+
+$m->callback( QueueObj => $QueueObj, title => \$title, results => \@results, ARGSRef => \%ARGS );
+
+$QueueObj->Disabled && Abort(loc("Cannot create tickets in a disabled queue."));
+
+my $CFs = $QueueObj->TicketCustomFields();
+
+my $ValidCFs = $m->comp(
+ '/Elements/ValidateCustomFields',
+ CustomFields => $CFs,
+ ARGSRef => \%ARGS
+);
+
+# {{{ deal with deleting uploaded attachments
+foreach my $key (keys %ARGS) {
+ if ($key =~ m/^DeleteAttach-(.+)$/) {
+ delete $session{'Attachments'}{$1};
+ }
+ $session{'Attachments'} = { %{$session{'Attachments'} || {}} };
+}
+# }}}
+
+# {{{ store the uploaded attachment in session
+if ($ARGS{'Attach'}) { # attachment?
+ my $attachment = MakeMIMEEntity(
+ AttachmentFieldName => 'Attach'
+ );
+
+ my $file_path = Encode::decode_utf8("$ARGS{'Attach'}");
+ $session{'Attachments'} = {
+ %{$session{'Attachments'} || {}},
+ $file_path => $attachment,
+ };
+}
+# }}}
+
+# delete temporary storage entry to make WebUI clean
+unless (keys %{$session{'Attachments'}} and $ARGS{'id'} eq 'new') {
+ delete $session{'Attachments'};
+}
+
+my $checks_failure = 0;
+
+my $gnupg_widget = $m->comp('/Elements/GnuPG/SignEncryptWidget:new', Arguments => \%ARGS );
+$m->comp( '/Elements/GnuPG/SignEncryptWidget:Process',
+ self => $gnupg_widget,
+ QueueObj => $QueueObj,
+);
+
+
+if ( !exists $ARGS{'AddMoreAttach'} && ($ARGS{'id'}||'') eq 'new' ) {
+ my $status = $m->comp('/Elements/GnuPG/SignEncryptWidget:Check',
+ self => $gnupg_widget,
+ Operation => 'Create',
+ QueueObj => $QueueObj,
+ );
+ $checks_failure = 1 unless $status;
+}
+
+# check email addresses for RT's
+{
+ foreach my $field ( qw(Requestors Cc AdminCc) ) {
+ my $value = $ARGS{ $field };
+ next unless defined $value && length $value;
+
+ my @emails = Email::Address->parse( $value );
+ foreach my $email ( grep RT::EmailParser->IsRTAddress($_->address), @emails ) {
+ push @results, loc("[_1] is an address RT receives mail at. Adding it as a '[_2]' would create a mail loop", $email->format, loc($field =~ /^(.*?)s?$/) );
+ $checks_failure = 1;
+ $email = undef;
+ }
+ $ARGS{ $field } = join ', ', map $_->format, grep defined, @emails;
+ }
+}
+
+my $skip_create = 0;
+$m->callback( CallbackName => 'BeforeCreate', ARGSRef => \%ARGS, skip_create => \$skip_create,
+ checks_failure => $checks_failure, results => \@results );
+
+if ((!exists $ARGS{'AddMoreAttach'}) and (defined($ARGS{'id'}) and $ARGS{'id'} eq 'new')) { # new ticket?
+ if ( $ValidCFs && !$checks_failure && !$skip_create ) {
+ $m->comp('show', %ARGS);
+ $RT::Logger->crit("After display call; error is $@");
+ $m->abort();
+ }
+ elsif ( !$ValidCFs ) {
+ # Invalid CFs
+ while (my $CF = $CFs->Next) {
+ my $msg = $m->notes('InvalidField-' . $CF->Id) or next;
+ push @results, $CF->Name . ': ' . $msg;
+ }
+ }
+}
+
+
+
+
+</%init>
+<&| /m/_elements/wrapper &>
+<& /Elements/ListActions, actions => \@results &>
+<form action="<% RT->Config->Get('WebPath') %>/m/ticket/create" method="post" enctype="multipart/form-data" name="TicketCreate">
+<input type="hidden" class="hidden" name="id" value="new" />
+% $m->callback( CallbackName => 'FormStart', QueueObj => $QueueObj, ARGSRef => \%ARGS );
+% if ($gnupg_widget) {
+<& /Elements/GnuPG/SignEncryptWidget:ShowIssues, self => $gnupg_widget &>
+% }
+<div id="Ticket-Create-basics">
+<&| /Widgets/TitleBox, title => $title &>
+<%perl>
+
+$showrows->(
+
+ loc('Queue') => $m->scomp( '/Ticket/Elements/ShowQueue', QueueObj => $QueueObj )
+ . '<input type="hidden" class="hidden" name="Queue" value="'. $QueueObj->Name .'" />',
+
+ loc('Status') =>
+
+ $m->scomp(
+ "/Elements/SelectStatus",
+ Name => "Status",
+ Default => $ARGS{Status} || 'new',
+ DefaultValue => 0,
+ SkipDeleted => 1
+ ),
+
+ loc("Owner") =>
+
+ $m->scomp(
+ "/Elements/SelectOwner",
+ Name => "Owner",
+ QueueObj => $QueueObj,
+ Default => $ARGS{Owner} || $RT::Nobody->Id,
+ DefaultValue => 0
+ ),
+
+ loc("Requestors") => $m->scomp(
+ "/Elements/EmailInput",
+ Name => 'Requestors',
+ Size => '40',
+ Default => $ARGS{Requestors} || $session{CurrentUser}->EmailAddress
+ ),
+
+ loc("Cc") =>
+
+ $m->scomp( "/Elements/EmailInput", Name => 'Cc', Size => '40', Default => $ARGS{Cc} )
+ . '<span class="comment"><i><font size="-2">'
+ . loc(
+ "(Sends a carbon-copy of this update to a comma-delimited list of email addresses. These people <strong>will</strong> receive future updates.)"
+ )
+ . '</font></i></span>',
+
+ loc("Admin Cc") =>
+
+ $m->scomp( "/Elements/EmailInput", Name => 'AdminCc', Size => '40', Default => $ARGS{AdminCc} )
+ . '<span class="comment" colspan="2"><i><font size="-2">'
+ . loc(
+ "(Sends a carbon-copy of this update to a comma-delimited list of administrative email addresses. These people <strong>will</strong> receive future updates.)"
+ )
+ . '</font></i></span>',
+
+ loc("Subject") =>
+
+ '<input name="Subject" size="60" maxsize="200" value="'.($ARGS{Subject} || '').'" />',
+
+);
+
+
+$m->scomp("/Ticket/Elements/EditCustomFields", %ARGS, QueueObj => $QueueObj );
+
+
+$m->scomp("/Ticket/Elements/EditTransactionCustomFields", %ARGS, QueueObj => $QueueObj );
+
+</%perl>
+% if (exists $session{'Attachments'}) {
+
+<%loc("Attached file") %>
+
+<%loc("Check box to delete")%><br />
+% foreach my $attach_name (keys %{$session{'Attachments'}}) {
+<input type="checkbox" class="checkbox" name="DeleteAttach-<%$attach_name%>" value="1" /><%$attach_name%><br />
+% } # end of foreach
+
+
+% } # end of if
+
+<%perl>
+$showrows->(
+ loc("Attach file") =>
+
+ '<div class="value" colspan="5">
+<input type="file" name="Attach" />
+<input type="submit" class="button" name="AddMoreAttach" value="' . loc("Add More Files") . '" />'
+);
+</%perl>
+
+
+% if ( $gnupg_widget ) {
+%$m->scomp("/Elements/GnuPG/SignEncryptWidget", self => $gnupg_widget, QueueObj => $QueueObj )
+% }
+
+<%perl>
+$showrows->(
+ loc("Describe the issue below") =>
+ $m->scomp(
+ "/Elements/MessageBox", exists $ARGS{Content} ? (Default => $ARGS{Content}, IncludeSignature => 0 ) :
+( QuoteTransaction => $QuoteTransaction )));
+
+
+$m->scomp("/Elements/Submit", Label => loc("Create"));
+
+</%perl>
+
+ <div class="ticket-info-basics">
+ <&| /Widgets/TitleBox, title => loc('The Basics'),
+ title_class=> 'inverse',
+ color => "#993333" &>
+<%perl>
+$showrows->(
+ loc("Priority") => $m->scomp(
+ "/Elements/SelectPriority",
+ Name => "InitialPriority",
+ Default => $ARGS{InitialPriority} ? $ARGS{InitialPriority} : $QueueObj->InitialPriority,
+ ),
+ loc("Final Priority") => $m->scomp(
+ "/Elements/SelectPriority",
+ Name => "FinalPriority",
+ Default => $ARGS{FinalPriority} ? $ARGS{FinalPriority} : $QueueObj->FinalPriority,
+ ),
+
+ loc("Time Estimated") => $m->scomp(
+ "/Elements/EditTimeValue",
+ Name => 'TimeEstimated',
+ Default => $ARGS{TimeEstimated} || '',
+ InUnits => $ARGS{'TimeEstimated-TimeUnits'}
+ ),
+
+ loc("Time Worked") => $m->scomp(
+ "/Elements/EditTimeValue",
+ Name => 'TimeWorked',
+ Default => $ARGS{TimeWorked} || '',
+ InUnits => $ARGS{'TimeWorked-TimeUnits'}
+ ),
+
+ loc("Time Left") => $m->scomp(
+ "/Elements/EditTimeValue",
+ Name => 'TimeLeft',
+ Default => $ARGS{TimeLeft} || '',
+ InUnits => $ARGS{'TimeLeft-TimeUnits'}
+ ),
+);
+
+</%perl>
+</&>
+<&|/Widgets/TitleBox, title => loc("Dates"),
+ title_class=> 'inverse',
+ color => "#663366" &>
+
+<%perl>
+$showrows->(
+ loc("Starts") => $m->scomp( "/Elements/SelectDate", Name => "Starts", Default => ( $ARGS{Starts} || '' )),
+ loc("Due") => $m->scomp( "/Elements/SelectDate", Name => "Due", Default => ($ARGS{Due} || '' ))
+);
+
+</%perl>
+</&>
+
+<&|/Widgets/TitleBox, title => loc('Links'), title_class=> 'inverse' &>
+
+<em><%loc("(Enter ticket ids or URLs, separated with spaces)")%></em>
+
+<%perl>
+$showrows->(
+ loc("Depends on") => '<input size="10" name="new-DependsOn" value="' . ($ARGS{'new-DependsOn'} || '' ). '" />',
+ loc("Depended on by") => '<input size="10" name="DependsOn-new" value="' . ($ARGS{'DependsOn-new'} || '' ) . '" />',
+ loc("Parents") => '<input size="10" name="new-MemberOf" value="' . ($ARGS{'new-MemberOf'} || '') . '" />',
+ loc("Children") => '<input size="10" name="MemberOf-new" value="' . ($ARGS{'MemberOf-new'} || '') . '" />',
+ loc("Refers to") => '<input size="10" name="new-RefersTo" value="' . ($ARGS{'new-RefersTo'} || '') . '" />',
+ loc("Referred to by") => '<input size="10" name="RefersTo-new" value="' . ($ARGS{'RefersTo-new'} || ''). '" />'
+);
+</%perl>
+
+</&>
+
+
+<& /Elements/Submit, Label => loc("Create") &>
+</form>
+</&>
+</&>
diff --git a/html/m/ticket/show b/html/m/ticket/show
index 701f52c..9909a85 100644
--- a/html/m/ticket/show
+++ b/html/m/ticket/show
@@ -2,8 +2,100 @@
$id => undef
</%args>
<%init>
-my $t = RT::Ticket->new($session{CurrentUser});
-$t->Load($id);
+my $TicketObj;
+my @Actions;
+
+if ($ARGS{'id'} eq 'new') {
+ # {{{ Create a new ticket
+
+ my $Queue = new RT::Queue( $session{'CurrentUser'} );
+ $Queue->Load($ARGS{'Queue'});
+ unless ( $Queue->id ) {
+ Abort('Queue not found');
+ }
+
+ unless ( $Queue->CurrentUserHasRight('CreateTicket') ) {
+ Abort('You have no permission to create tickets in that queue.');
+ }
+
+ ($TicketObj, @Actions) = CreateTicket(
+ Attachments => delete $session{'Attachments'},
+ %ARGS,
+ );
+ unless ( $TicketObj->CurrentUserHasRight('ShowTicket') ) {
+ Abort("No permission to view newly created ticket #".$TicketObj->id.".");
+ }
+ # }}}
+} else {
+ $TicketObj ||= LoadTicket($ARGS{'id'});
+
+ $m->callback( CallbackName => 'BeforeProcessArguments',
+ TicketObj => $TicketObj,
+ ActionsRef => \@Actions, ARGSRef => \%ARGS );
+ if ( defined $ARGS{'Action'} ) {
+ if ($ARGS{'Action'} =~ /^(Steal|Kill|Take|SetTold)$/) {
+ my $action = $1;
+ my ($res, $msg) = $TicketObj->$action();
+ push(@Actions, $msg);
+ }
+ }
+
+ $m->callback(CallbackName => 'ProcessArguments',
+ Ticket => $TicketObj,
+ ARGSRef => \%ARGS,
+ Actions => \@Actions);
+
+ $ARGS{UpdateAttachments} = $session{'Attachments'};
+ push @Actions,
+ ProcessUpdateMessage(
+ ARGSRef => \%ARGS,
+ Actions => \@Actions,
+ TicketObj => $TicketObj,
+ );
+ delete $session{'Attachments'};
+
+ #Process status updates
+ push @Actions, ProcessTicketWatchers(ARGSRef => \%ARGS, TicketObj => $TicketObj );
+ push @Actions, ProcessTicketBasics( ARGSRef => \%ARGS, TicketObj => $TicketObj );
+ push @Actions, ProcessTicketLinks( ARGSRef => \%ARGS, TicketObj => $TicketObj );
+ push @Actions, ProcessTicketDates( ARGSRef => \%ARGS, TicketObj => $TicketObj );
+ push @Actions, ProcessObjectCustomFieldUpdates(ARGSRef => \%ARGS, TicketObj => $TicketObj );
+
+ # XXX: we shouldn't block actions here if user has no right to see the ticket,
+ # but we should allow him to see actions he has done
+ unless ($TicketObj->CurrentUserHasRight('ShowTicket')) {
+ Abort("No permission to view ticket");
+ }
+ if ( $ARGS{'MarkAsSeen'} ) {
+ $TicketObj->SetAttribute(
+ Name => 'User-'. $TicketObj->CurrentUser->id .'-SeenUpTo',
+ Content => $TicketObj->LastUpdated,
+ );
+ push @Actions, loc('Marked all messages as seen');
+ }
+}
+
+$m->callback(
+ CallbackName => 'BeforeDisplay',
+ TicketObj => \$TicketObj,
+ Actions => \@Actions,
+ ARGSRef => \%ARGS,
+);
+
+# This code does automatic redirection if any updates happen.
+
+if (@Actions) {
+
+ # We've done something, so we need to clear the decks to avoid
+ # resubmission on refresh.
+ # But we need to store Actions somewhere too, so we don't lose them.
+ my $key = Digest::MD5::md5_hex( rand(1024) );
+ push @{ $session{"Actions"}->{$key} ||= [] }, @Actions;
+ $session{'i'}++;
+ my $url = RT->Config->Get('WebURL') . "/m/ticket/show?id=" . $TicketObj->id . "&results=" . $key;
+ $url .= '#' . $ARGS{Anchor} if $ARGS{Anchor};
+ RT::Interface::Web::Redirect($url);
+}
</%init>
<&| /m/_elements/wrapper &>
@@ -11,27 +103,27 @@ $t->Load($id);
<&| /Widgets/TitleBox, title => loc('The Basics'),
class => 'ticket-info-basics',
&>
- <& /Ticket/Elements/ShowBasics, Ticket => $t &>
+ <& /Ticket/Elements/ShowBasics, Ticket => $TicketObj &>
</&>
-% if ($t->CustomFields->First) {
+% if ($TicketObj->CustomFields->First) {
<&| /Widgets/TitleBox, title => loc('Custom Fields'),
- title_href => RT->Config->Get('WebPath')."/Ticket/Modify.html?id=".$t->Id,
+ title_href => RT->Config->Get('WebPath')."/Ticket/Modify.html?id=".$TicketObj->Id,
class => 'ticket-info-cfs',
&>
- <& /Ticket/Elements/ShowCustomFields, Ticket => $t &>
+ <& /Ticket/Elements/ShowCustomFields, Ticket => $TicketObj &>
</&>
% }
<&| /Widgets/TitleBox, title => loc('People'),
class => 'ticket-info-people',
&>
- <& /Ticket/Elements/ShowPeople, Ticket => $t &>
+ <& /Ticket/Elements/ShowPeople, Ticket => $TicketObj &>
</&>
- <& /Ticket/Elements/ShowAttachments, Ticket => $t &>
+ <& /Ticket/Elements/ShowAttachments, Ticket => $TicketObj &>
- <& /Ticket/Elements/ShowRequestor, Ticket => $t &>
+ <& /Ticket/Elements/ShowRequestor, Ticket => $TicketObj &>
% if ( RT->Config->Get('EnableReminders') ) {
<&|/Widgets/TitleBox, title => loc("Reminders"),
@@ -39,7 +131,7 @@ $t->Load($id);
&>
<table><tr><td>
<form action="<%RT->Config->Get('WebPath')%>/Ticket/Display.html" method="post">
- <& /Ticket/Elements/Reminders, Ticket => $t, ShowCompleted => 0 &>
+ <& /Ticket/Elements/Reminders, Ticket => $TicketObj, ShowCompleted => 0 &>
<div align="right"><input type="submit" class="button" value="<&|/l&>Save</&>" /></div>
</form>
</td></tr></table>
@@ -49,13 +141,13 @@ $t->Load($id);
<&| /Widgets/TitleBox, title => loc("Dates"),
class => 'ticket-info-dates',
&>
- <& /Ticket/Elements/ShowDates, Ticket => $t &>
+ <& /Ticket/Elements/ShowDates, Ticket => $TicketObj &>
</&>
<&| /Widgets/TitleBox, title => loc('Links'),
class => 'ticket-info-links',
&>
- <& /Elements/ShowLinks, Ticket => $t &>
+ <& /Elements/ShowLinks, Ticket => $TicketObj &>
</&>
</&>
-----------------------------------------------------------------------
More information about the Bps-public-commit
mailing list