diff options
Diffstat (limited to 'rt')
-rw-r--r-- | rt/FREESIDE_MODIFIED | 6 | ||||
-rw-r--r-- | rt/sbin/rt-test-dependencies.in | 1 | ||||
-rw-r--r-- | rt/share/html/Elements/CalendarDaySchedule | 7 | ||||
-rw-r--r-- | rt/share/html/Elements/CalendarSlotSchedule | 155 | ||||
-rwxr-xr-x | rt/share/html/Elements/Header | 30 | ||||
-rw-r--r-- | rt/share/html/NoAuth/css/calendar.css | 96 | ||||
-rw-r--r-- | rt/share/html/Search/Calendar.html | 2 | ||||
-rw-r--r-- | rt/share/html/Search/Schedule.html | 224 | ||||
-rwxr-xr-x | rt/share/html/Ticket/Display.html | 2 | ||||
-rwxr-xr-x | rt/share/html/Ticket/ModifyCustomFieldsPopup.html | 129 | ||||
-rw-r--r-- | rt/share/static/images/created.png (renamed from rt/share/html/NoAuth/images/created.png) | bin | 994 -> 994 bytes | |||
-rw-r--r-- | rt/share/static/images/created_due.png (renamed from rt/share/html/NoAuth/images/created_due.png) | bin | 997 -> 997 bytes | |||
-rw-r--r-- | rt/share/static/images/due.png (renamed from rt/share/html/NoAuth/images/due.png) | bin | 936 -> 936 bytes | |||
-rw-r--r-- | rt/share/static/images/reminder.png (renamed from rt/share/html/NoAuth/images/reminder.png) | bin | 921 -> 921 bytes | |||
-rw-r--r-- | rt/share/static/images/resolved.png (renamed from rt/share/html/NoAuth/images/resolved.png) | bin | 229 -> 229 bytes | |||
-rw-r--r-- | rt/share/static/images/started.png (renamed from rt/share/html/NoAuth/images/started.png) | bin | 934 -> 934 bytes | |||
-rw-r--r-- | rt/share/static/images/starts.png (renamed from rt/share/html/NoAuth/images/starts.png) | bin | 935 -> 935 bytes | |||
-rw-r--r-- | rt/share/static/images/starts_due.png (renamed from rt/share/html/NoAuth/images/starts_due.png) | bin | 173 -> 173 bytes | |||
-rw-r--r-- | rt/share/static/images/updated.png (renamed from rt/share/html/NoAuth/images/updated.png) | bin | 191 -> 191 bytes | |||
-rw-r--r-- | rt/share/static/images/week-collapse.gif (renamed from rt/share/html/NoAuth/images/week-collapse.gif) | bin | 137 -> 137 bytes | |||
-rw-r--r-- | rt/share/static/images/week-collapse.xcf (renamed from rt/share/html/NoAuth/images/week-collapse.xcf) | bin | 1996 -> 1996 bytes | |||
-rw-r--r-- | rt/share/static/images/week-expand.gif (renamed from rt/share/html/NoAuth/images/week-expand.gif) | bin | 150 -> 150 bytes | |||
-rw-r--r-- | rt/share/static/images/week-expand.xcf (renamed from rt/share/html/NoAuth/images/week-expand.xcf) | bin | 1621 -> 1621 bytes |
23 files changed, 575 insertions, 77 deletions
diff --git a/rt/FREESIDE_MODIFIED b/rt/FREESIDE_MODIFIED index ace0d499b..05ffb2a46 100644 --- a/rt/FREESIDE_MODIFIED +++ b/rt/FREESIDE_MODIFIED @@ -165,3 +165,9 @@ share/html/Search/Elements/PickBasics lib/RT/CustomField.pm share/html/Admin/CustomFields/Modify.html share/html/Ticket/Create.html + +#allow RedirectToBasics to be set from schedule-appointments, RT#38481 +share/html/Search/Schedule.html +share/html/Elements/CalendarSlotSchedule +share/html/Ticket/Display.html + diff --git a/rt/sbin/rt-test-dependencies.in b/rt/sbin/rt-test-dependencies.in index 505d18add..ff987283b 100644 --- a/rt/sbin/rt-test-dependencies.in +++ b/rt/sbin/rt-test-dependencies.in @@ -273,7 +273,6 @@ Crypt::SSLeay Net::SSL LWP::UserAgent 6.0 LWP::Protocol::https -Mozilla::CA . $deps{'CLI'} = [ text_to_hash( << '.') ]; diff --git a/rt/share/html/Elements/CalendarDaySchedule b/rt/share/html/Elements/CalendarDaySchedule index 5be5b06bc..bac9a78d4 100644 --- a/rt/share/html/Elements/CalendarDaySchedule +++ b/rt/share/html/Elements/CalendarDaySchedule @@ -31,8 +31,13 @@ $CurrentUser => undef % my( $starts, $due, $col, $t ) = @{ $schedule{'scheduled'}->{$id} }; % my $s = int(($starts-$stime)/10); % my $e = int(($due-$stime)/10)-1; + +% #false laziness w/misc/xmlhttp-ticket-update.html & CalendarSlotSchedule +% my %hash = $m->comp('/Ticket/Elements/Customers', Ticket => $t); +% my @cust_main = values( %{$hash{cust_main}} ); + <AREA - onmouseover = "overlib('<%$id%>: <% FS::sched_avail::pretty_time($starts). '-'. FS::sched_avail::pretty_time($due) %><BR>XX miles away<BR>more info', WRAP, BGCOLOR, '#000000', FGCOLOR, '#<%$col%>')" + onmouseover = "overlib('<% FS::sched_avail::pretty_time($starts). '-'. FS::sched_avail::pretty_time($due) %><BR>' + <% $cust_main[0]->_FreesideURILabel |js_string %>, WRAP, BGCOLOR, '#000000', FGCOLOR, '#<%$col%>')" onmouseout = "nd(); return true;" shape = "rect" coords = "<%$s%>,0,<%$e%>,<%$height%>" diff --git a/rt/share/html/Elements/CalendarSlotSchedule b/rt/share/html/Elements/CalendarSlotSchedule index ff3e6342c..b82997be8 100644 --- a/rt/share/html/Elements/CalendarSlotSchedule +++ b/rt/share/html/Elements/CalendarSlotSchedule @@ -9,6 +9,7 @@ $LengthMin => $default_timestep $custnum => undef $pkgnum => undef + $RedirectToBasics => 0 </%ARGS> % foreach my $username ( @username ) { % @@ -19,7 +20,12 @@ % % my $bgcolor = '666666;border-color:#555555'; % my $content = ''; +% my $link = ''; % my $selectable = 0; +% my $draggable_ticketid = 0; +% my $draggable_length = 0; +% my $droppable = 0; +% my $cells = 0; % % #white out available times % foreach my $avail ( @{ $schedule{'avail'} } ) { @@ -44,58 +50,123 @@ % $selectable = 0; % % if ( $starts >= $tod_row ) { #first row -% $content .= ($content?', ':''). $id. -% ': '. FS::sched_avail::pretty_time($starts). '-'. -% FS::sched_avail::pretty_time($due); +% +% #false laziness w/misc/xmlhttp-ticket-update.html & CalendarDaySchedule +% my %hash = $m->comp('/Ticket/Elements/Customers', Ticket => $t); +% my @cust_main = values( %{$hash{cust_main}} ); +% +% $content .= ($content?', ':''). #$id. ': '. +% #false laziness w/xmlhttp-ticket-update.html +% FS::sched_avail::pretty_time($starts). '-'. +% FS::sched_avail::pretty_time($due). +% ': '. $cust_main[0]->_FreesideURILabel; % #'install for custname XX miles away'; #XXX placeholder/more +% $link = qq( <A HREF="$RT::WebPath/Ticket/Display.html?id=$id" target="_blank">view</A> ). +% include('/elements/popup_link.html', +% action=>$RT::WebPath.'/Ticket/ModifyCustomFieldsPopup.html?id='.$id, +% label =>'edit', +% actionlabel => 'Edit appointment', +% height => 436, # better: A + B * (num_custom_fields) +% ); +% $draggable_ticketid = $id; +% $draggable_length = $due - $starts; +% +% $cells = int( ($due-$starts) / $timestep ); +% $cells++ if ($due-$starts) % $timestep; +% % #} else { % # $content .= ($content?', ':''). $id; % } % } +% +% my $td_id = 'td_'. $Date->epoch. '_'. $tod_row. '_'. $username; - <td style="background:#<%$bgcolor%>" - class="<% $selectable ? 'weeklyselectable' : 'weekly' %>" -%# <% $is_today ? 'today' -%# : $is_yesterday ? 'yesterday' -%# : $is_aweekago ? 'aweekago' -%# : '' -%# %>" + <td style = "background-color:#<%$bgcolor%>" + ID="<% $td_id %>" + class = "<% ($selectable && $custnum && $LengthMin) ? 'weeklyselectable' : 'weekly' %>" +%# <% $is_today ? 'today' +%# : $is_yesterday ? 'yesterday' +%# : $is_aweekago ? 'aweekago' +%# : '' +%# %>" % if ( $selectable ) { % -% #XXX for now, construct a ticket creation URL -% # eventually, do much the same, but say "appointment made", show time -% # and date, have # options to do things with it? etc. -% # then redir back to customer/appointment view i guess -% -% #abstraction is leaking like a sieve... linking back to freeside cust -% # (XXX and eventually, package) -% my $cust_main = qsearchs('cust_main', { custnum=>$custnum } ) -% or die "unknown custnum $custnum"; -% my $Queue = $cust_main->agent->ticketing_queueid || 1; # || $default_queueid;#XXX really, pick pkg_category queue -% my $member = "freeside://freeside/cust_main/$custnum"; -% -%warn my $Starts = int($tod_row/60). ':'. sprintf('%02d',$tod_row%60). ':00'; -%warn my $Due = int(($tod_row+$LengthMin)/60). ':'. -% sprintf('%02d',($tod_row+$LengthMin)%60). ':00'; -% -% my $url = $RT::WebPath. '/Ticket/Display.html?id=new'. -% "&Queue=$Queue". -% "&Owner=$username". -% '&Starts='. $Date->strftime('%F').'%20'. $Starts. -% '&Due='. $Date->strftime('%F').'%20'. $Due. -% '&new-MemberOf='. $member. #XXX uri_escape? -% '&Status=new'; -% #'&Requestors='. #XXX Freeside customer requestor(s) (package? +% if ( $custnum && $LengthMin ) { +% +% #XXX for now, construct a ticket creation URL +% # eventually, do much the same, but say "appointment made", show time +% # and date, have # options to do things with it? etc. +% # then redir back to customer/appointment view i guess +% +% #abstraction is leaking like a sieve... linking back to freeside cust +% # (XXX and eventually, package) +% my $cust_main = qsearchs('cust_main', { custnum=>$custnum } ) +% or die "unknown custnum $custnum"; +% +% my $conf = new FS::Conf; +% my $Queue = $conf->config('ticket_system-appointment-queueid') +% or die "ticket_system-appointment-queueid configuration not set"; +% +% my $member = "freeside://freeside/cust_main/$custnum"; +% +% my $Starts = int($tod_row/60). ':'. sprintf('%02d',$tod_row%60). ':00'; +% my $Due = int(($tod_row+$LengthMin)/60). ':'. +% sprintf('%02d',($tod_row+$LengthMin)%60). ':00'; +% +% my $url = $RT::WebPath. '/Ticket/Display.html?id=new'. +% "&Queue=$Queue". +% "&Owner=$username". +% '&Starts='. $Date->strftime('%F').'%20'. $Starts. +% '&Due='. $Date->strftime('%F').'%20'. $Due. +% '&new-MemberOf='. $member. #XXX uri_escape? +% '&Status=new'. +% '&RedirectToBasics='.$RedirectToBasics; +% #'&Requestors='. #XXX Freeside customer requestor(s) (package? - onmouseover = "boxon(this);" - onmouseout = "boxoff(this);" - title = "<% 'Make appointment for '. - FS::sched_avail::pretty_time($tod_row). '-'. - FS::sched_avail::pretty_time($tod_row+$LengthMin) - %>" - onclick = "window.location.href = '<% $url %>'" + onmouseover = "boxon(this);" + onmouseout = "boxoff(this);" + title = "<% 'Make appointment for '. + FS::sched_avail::pretty_time($tod_row). '-'. + FS::sched_avail::pretty_time($tod_row+$LengthMin) + %>" + onclick = "window.location.href = '<% $url %>'" +% +% } else { +% $droppable = 1; +% } +% % } - ><% $content %></td> + ><% $content |h %><% $link |n %></td> + <SCRIPT TYPE="text/javascript"> + + $('#<% $td_id %>').data('username', "<% $username %>"); + $('#<% $td_id %>').data('starts', <% $Date->epoch + $tod_row*60 %>); + $('#<% $td_id %>').data('epoch', <% $Date->epoch %>); + $('#<% $td_id %>').data('tod_row', <% $tod_row %>); + +% if ( $droppable ) { + $('#<% $td_id %>').droppable({ + over: boxon_drop, + drop: reschedule_appointment, + tolerance: 'pointer' + }); +% } + +% if ( $draggable_ticketid ) { + $('#<% $td_id %>').draggable({ + containment: '.titlebox-content', +%# revert: 'invalid', + revert: true, + revertDuration: 0, + stop: clear_drag_hi, + }); + $('#<% $td_id %>').data('ticketid', <% $draggable_ticketid %>); + $('#<% $td_id %>').data('length', <% $draggable_length * 60 %>); + $('#<% $td_id %>').data('cells', <% $cells %>); + $('#<% $td_id %>').data('bgcolor', "#<% $bgcolor %>"); +% } + + </SCRIPT> % } <%ONCE> my $default_slots = RT->Config->Get('CalendarWeeklySlots') || 5; diff --git a/rt/share/html/Elements/Header b/rt/share/html/Elements/Header index 1f6035d7d..d26448463 100755 --- a/rt/share/html/Elements/Header +++ b/rt/share/html/Elements/Header @@ -45,14 +45,27 @@ %# those contributions and any derivatives thereof. %# %# END BPS TAGGED BLOCK }}} +% if ( $Popup ) { +<& /elements/header-popup.html, { + 'title_noescape' => $Title, + 'head' => $head, + 'etc' => $etc, + 'nobr' => 1, + #'nocss' => 1, + 'no_jquery' => $JavaScript, + } +&> +% } else { <& /elements/header.html, { - 'title' => $Title, - 'head' => $head, - 'etc' => $etc, + 'title_noescape' => $Title, + 'head' => $head, + 'etc' => $etc, #make space for RT menu for now# 'nobr' => 1, - 'nocss' => 1, + 'nocss' => 1, + 'no_jquery' => $JavaScript, } &> +% } <%INIT> #for "Site CSS from theme editor" below #use Scalar::Util qw(blessed); @@ -113,9 +126,11 @@ if ($JavaScript) { $head .= $m->scomp('HeaderJavascript', focus => $Focus, onload => $onload, RichText => $RichText ); } -my $stylesheet_plugin = "/NoAuth/css/$style/InHeader"; -if ($m->comp_exists($stylesheet_plugin) ) { - $head .= $m->scomp($stylesheet_plugin); +if ($JavaScript) { + my $stylesheet_plugin = "/NoAuth/css/$style/InHeader"; + if ($m->comp_exists($stylesheet_plugin) ) { + $head .= $m->scomp($stylesheet_plugin); + } } #<!-- Site CSS from theme editor --> @@ -151,4 +166,5 @@ $LinkRel => undef $JavaScript => 1 $SkipDoctype => 0 $RichText => 1 +$Popup => 0 </%ARGS> diff --git a/rt/share/html/NoAuth/css/calendar.css b/rt/share/html/NoAuth/css/calendar.css index 7092d7672..566f969ba 100644 --- a/rt/share/html/NoAuth/css/calendar.css +++ b/rt/share/html/NoAuth/css/calendar.css @@ -71,18 +71,6 @@ table.rtxcalendar tbody th { font-weight: normal; } -table.rtxcalendar td.weekly { - width: auto; -} - -table.rtxcalendar td.weeklyselectable { - width: auto; -} - -table.rtxcalendar td.weeklyselectable:hover { - cursor: pointer; -} - table.rtxcalendar td.offmonth { background: #f8f8f8; color: #aaa; @@ -133,3 +121,87 @@ table.rtxcalendar td.labels { border-bottom: 1px solid #eeeeee; } + + +.rtxweeklycalendar .tooltip{position:relative;z-index:1;} +.rtxweeklycalendar .tooltip:hover{z-index:5;color:#000;} +.rtxweeklycalendar .tooltip span.tip{display: none; text-align:left;} + +.rtxweeklycalendar div.tooltip:hover span.tip{ +display:block; +position:absolute; +top:12px; left:24px; width:350px; +border:1px solid #555; +background-color:#fff; +padding: 4px; +font-size: 0.8em; +color:#505050; +} + +.rtxweeklycalendar .date { + text-align: right; + background-color: #f8f8ff; + width:100%; +} + +table.rtxweeklycalendar { + width:100%; + border-collapse: collapse; + border: 1px solid #d0d0d0; + margin-bottom: 6px; +} + +table.rtxweeklycalendar td { + border: 1px solid #d7d7d7; + background: #fff; + vertical-align: top; +} + +table.rtxweeklycalendar th { + border: 1px solid #d7d7d7; + background: #eef; +} +table.rtxweeklycalendar tbody th { + border: 1px solid #d7d7d7; + background: #eee; + font-weight: normal; +} + +table.rtxweeklycalendar td.weekly { + width: auto; +} + +table.rtxweeklycalendar td.weeklyselectable { + width: auto; +} + +table.rtxweeklycalendar td.weeklyselectable:hover { + cursor: pointer; +} + +table.rtxweeklycalendar td.controls { + background: #eeeeee; + width: 1%; + border-top: 1px solid #eeeeee; + border-left: 1px solid #eeeeee; + border-bottom: 1px solid #eeeeee; + border-right: 1px solid #eeeeee; + vertical-align: middle; +} + +table.rtxweeklycalendar td.controls:hover { + background-color: #CFDEFF; +} + +table.rtxweeklycalendar td.labels { + background: #eeeeee; + width: 1%; + border-top: 1px solid #eeeeee; + border-left: 1px solid #eeeeee; + border-bottom: 1px solid #eeeeee; +} + +.ui-effects-transfer { + border: 1px solid black; +} + diff --git a/rt/share/html/Search/Calendar.html b/rt/share/html/Search/Calendar.html index 092f6a5a1..2c19296f9 100644 --- a/rt/share/html/Search/Calendar.html +++ b/rt/share/html/Search/Calendar.html @@ -78,7 +78,7 @@ $DimPast => 0 </table> % } -<table class="rtxcalendar"> +<table class="<% $WeekDay ? 'rtxweeklycalendar' : 'rtxcalendar' %>"> <thead> diff --git a/rt/share/html/Search/Schedule.html b/rt/share/html/Search/Schedule.html index 34ba142bd..0dbe8c30b 100644 --- a/rt/share/html/Search/Schedule.html +++ b/rt/share/html/Search/Schedule.html @@ -1,14 +1,9 @@ -<& /Elements/Header, Title => 'Schedule' &> - -%#init_overlib.html -%foreach my $file (@files) { -<SCRIPT TYPE="text/javascript" SRC="<%$fsurl%>elements/<%$file%>.js"></SCRIPT> -%} - -<SCRIPT TYPE="text/javascript" SRC="<%$fsurl%>elements/jquery.js"></SCRIPT> +<& /Elements/Header, Title => 'Schedule', JavaScript => 0 &> <SCRIPT TYPE="text/javascript"> +% if ( $cells ) { + function boxon(what) { var $this = $(what); for ( var c=0; c < <%$cells%>; c++) { @@ -48,13 +43,206 @@ } } + +% } + +% # it would be better if we had draggable-specific droppables, but this will prevent overlap for now... + function can_drop ($where, cells) { + for (var c=0; c < cells; c++) { + if (!$where.is('.ui-droppable')) { + return false; + } + var rownum = $where.parent().prevAll('tr').length; + var colnum = $where.prevAll('td').length; + $where = $where.parent().parent().children('tr').eq(rownum+1).children('td').eq(colnum); + } + return true; + } + + var drag_cells = 0; + var drag_hi; + + // on drag stop (regardless of if it was dropped) + function clear_drag_hi () { + if ( drag_hi ) { + boxoff_do(drag_hi); + drag_hi = undefined; + } + } + + // on drag over + function boxon_drop(event, ui) { + //var $this = $(what); + var $this = $(this); + + drag_cells = ui.draggable.data('cells'); + + clear_drag_hi(); + + if (!can_drop($this, drag_cells)) return; + + drag_hi = $this; + + for ( var c=0; c < drag_cells; c++) { + + /* well, its not exactly what i want, would prefer if it could properly + mouse in-out, but this sorta helps for now? + revisit when everthing else is working */ +/* $this.effect("highlight", {}, 1500); */ + + $this.css('background-color', '#ffffdd'); + if ( c == 0 ) { + $this.css('border-top', '1px double black'); + $this.css('border-left', '1px double black'); + $this.css('border-right', '1px solid black'); + } else if ( c == (drag_cells-1) ) { + $this.css('border-left', '1px double black'); + $this.css('border-right', '1px solid black'); + $this.css('border-bottom', '1px solid black'); + } else { + $this.css('border-left', '1px double black'); + $this.css('border-right', '1px solid black'); + } + + var rownum = $this.parent().prevAll('tr').length; + var colnum = $this.prevAll('td').length; + $this = $this.parent().parent().children('tr').eq(rownum+1).children('td').eq(colnum); + } + + + } + + // clears highlighted box, used by clear_hi_drag (drag stop event) + function boxoff_do(what) { + + var $this = what; + + for ( var c=0; c < drag_cells; c++) { + + //$this.css('background-color', ''); + //$this.css('border', ''); //IE8 woes, removes cell borders + $this.removeAttr('style'); //slightly "flashy" on cell changes under IE8 + //but at least it doesn't remove cell borders + + var rownum = $this.parent().prevAll('tr').length; + var colnum = $this.prevAll('td').length; + $this = $this.parent().parent().children('tr').eq(rownum+1).children('td').eq(colnum); + } + } + + // drop event + function reschedule_appointment( event, ui ) { + + var $this = $(this); + + if (!can_drop($this, ui.draggable.data('cells'))) return; + +% #get the ticket number and appointment length (from the draggable object) + var ticketid = ui.draggable.data('ticketid'); + var length = ui.draggable.data('length'); + var bgcolor = ui.draggable.data('bgcolor'); + +% #and.. the new date and time, and username (from the droppable object) + var starts = $this.data('starts'); + var username = $this.data('username'); + + var due = parseInt(starts) + parseInt(length); + + var n_epoch = $this.data('epoch'); + var n_st_tod_row = $this.data('tod_row'); + + var draggable = ui.draggable; + var droppable = $this; + draggable.effect( "transfer", { to: droppable }, 420 ); + +% #tell the backend to reschedule it + var url = "<% popurl(3) %>misc/xmlhttp-ticket-update.html?" + + "id=" + ticketid + ";starts=" + starts + ";due=" + due + + ";username=" + username; + + $.getJSON( url, function( data ) { + if ( data.error && data.error.length ) { +% #error? "that shouldn't happen" but should display + alert(data.error); +% #XX and should revert the dragable... + } else { + + //draggable.effect( "transfer", { to: droppable }, 1000 ); + + var label = data.sched_label; + +% #remove the old appointment entirely + var epoch = ui.draggable.data('epoch'); + var st_tod_row = ui.draggable.data('tod_row'); + var old_username = ui.draggable.data('username'); + var cells = ui.draggable.data('cells'); + for ( var c=0; c < cells; c++) { + var tod_row = parseInt(st_tod_row) + (c * <%$timestep%>); + var td_id = 'td_' + epoch + + '_' + String( tod_row ) + + '_' + old_username; + $('#'+td_id).css('background-color', '#FFFFFF'); + $('#'+td_id).text(''); +% #(and make those boxes droppable) + $('#'+td_id).droppable({ + over: boxon_drop, + drop: reschedule_appointment, + tolerance: 'pointer' + }); + } + +% #maybe use that animation which shows the box from point A to B + + clear_drag_hi(); + for ( var d=0; d < cells; d++) { + var n_tod_row = parseInt(n_st_tod_row) + (d * <%$timestep%>); + var n_td_id = 'td_' + n_epoch + + '_' + String( n_tod_row ) + + '_' + username; + $('#'+n_td_id).css('background-color', bgcolor); +% #remove their droppable + $('#'+n_td_id).droppable('destroy'); + if ( d == 0 ) { + var title = + label + + ' <A HREF="<%$RT::WebPath%>/Ticket/Display.html?id=' + ticketid + '" target="_blank">view</A> ' + + <% include('/elements/popup_link.html', + action=>$RT::WebPath.'/Ticket/ModifyCustomFieldsPopup.html?id=__MAGIC_TICKET_ID__', + label =>'edit', + actionlabel => 'Edit appointment', + height => 436, # better: A + B * (num_custom_fields) + ) |n,js_string + %>; + title = title.replace( /__MAGIC_TICKET_ID__/, ticketid ); + $('#'+n_td_id).html( title ); +% #(and make the top draggable, so we could do it all over again) + $('#'+n_td_id).draggable({ + containment: '.titlebox-content', +%# revert: 'invalid', + revert: true, + revertDuration: 0, + stop: clear_drag_hi, + }); + $('#'+n_td_id).data('ticketid', ticketid ); + $('#'+n_td_id).data('length', length ); + $('#'+n_td_id).data('cells', cells ); + $('#'+n_td_id).data('bgcolor', bgcolor ); + } + } + + } + + }); + + } + </SCRIPT> <& /Search/Calendar.html, @_, Query => "( Status = 'new' OR Status = 'open' OR Status = 'stalled') - AND ( Type = 'reminder' OR 'Type' = 'ticket' )", - #XXX and we have the magic custom field + AND ( Type = 'reminder' OR 'Type' = 'ticket' ) + AND Queue = $queueid ", slots => scalar(@usernames), Embed => 'Schedule.html', DimPast => 1, @@ -64,6 +252,7 @@ #oops, more freeside abstraction-leaking custnum => $ARGS{custnum}, pkgnum => $ARGS{pkgnum}, + RedirectToBasics => $ARGS{RedirectToBasics}, ], &> @@ -74,6 +263,11 @@ my $timestep = RT->Config->Get('CalendarWeeklySizeMin') || 30; #1/2h </%ONCE> <%init> +#abstraction-leaking +my $conf = new FS::Conf; +my $queueid = $conf->config('ticket_system-appointment-queueid') + or die "ticket_system-appointment-queueid configuration not set"; + my @files = (); #if ( ! $initialized ) { push @files, map "overlibmws$_", ( '', qw( _iframe _draggable _crossframe ) ); @@ -86,9 +280,13 @@ if ( ref($ARGS{username}) ) { } elsif ( $ARGS{username} ) { @usernames = ( $ARGS{username} ); } else { - #XXX shouldn't even get offered the link in the first place rather than perl - # barf, but this is better than erroring out later or empty @username - die "Can't schedule an appointment - no employees are configured as installers"; + #look them up ourslves... again, more FS abstraction-leaking, but + # we want to link to the schedule view, and better than doing this every + # menu render + use FS::Record qw( qsearch ); + use FS::sched_item; + my @sched_item = qsearch('sched_item', { 'disabled' => '', }); + @usernames = map $_->access_user->username, @sched_item; } ( my $LengthMin = $ARGS{LengthMin} ) =~ /^\d+$/ or die 'non-numeric LengthMin'; diff --git a/rt/share/html/Ticket/Display.html b/rt/share/html/Ticket/Display.html index 3c2385af2..82a822022 100755 --- a/rt/share/html/Ticket/Display.html +++ b/rt/share/html/Ticket/Display.html @@ -94,6 +94,7 @@ $TicketObj => undef $ShowHeaders => 0 $Collapsed => undef $ForceShowHistory => 0 +$RedirectToBasics => 0 </%ARGS> <%INIT> @@ -219,6 +220,7 @@ $m->callback( ); # This code does automatic redirection if any updates happen. +$m->notes('RedirectToBasics' => 1) if $RedirectToBasics; my $path = '/Ticket/'. ( $m->notes('RedirectToBasics') ? 'Modify.html' : 'Display.html' ); MaybeRedirectForResults( diff --git a/rt/share/html/Ticket/ModifyCustomFieldsPopup.html b/rt/share/html/Ticket/ModifyCustomFieldsPopup.html new file mode 100755 index 000000000..29aa9895b --- /dev/null +++ b/rt/share/html/Ticket/ModifyCustomFieldsPopup.html @@ -0,0 +1,129 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC +%# <sales@bestpractical.com> +%# +%# (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 }}} +% +%# false laziness w/Modify.html - better to modify it directly? +% +%#<& /Elements/Header, Title => loc('Modify ticket #[_1]', $TicketObj->Id) &> +<& /Elements/Header, Title=>'', Popup=>1 &> + +% $m->callback(CallbackName => 'BeforeActionList', Actions => \@results, ARGSRef => \%ARGS, Ticket => $TicketObj); + +<& /Elements/ListActions, actions => \@results &> +<form method="post" action="ModifyCustomFieldsPopup.html" enctype="multipart/form-data" name="TicketModify" id="TicketModify"> +% $m->callback( CallbackName => 'FormStart', ARGSRef => \%ARGS ); +<input type="hidden" class="hidden" name="id" value="<% $TicketObj->Id %>" /> + +<& /Elements/EditCustomFieldCustomGroupings, Object => $TicketObj &> + +%# <& /Elements/Submit, Name => 'SubmitTicket', Label => loc('Save Changes'), Caption => loc("If you've updated anything above, be sure to"), color => "#993333" &> + <div class="submit"> + <div class="buttons"> + <span class="caption">If you've updated anything above, be sure to</span> + <input type="submit" name="SubmitTicket" value="Save Changes" class="button" STYLE="color:black" /> + </div> + <div class="submit-clear"></div> + </div> + +</form> + +% $m->callback(CallbackName => 'AfterForm', ARGSRef => \%ARGS, Ticket => $TicketObj); +<%INIT> + +my $TicketObj = LoadTicket($id); +my $CustomFields = $TicketObj->CustomFields; + +my @results; +my $skip_update = 0; + +# Now let callbacks have a chance at editing %ARGS +$m->callback( TicketObj => $TicketObj, CustomFields => $CustomFields, ARGSRef => \%ARGS, skip_update => \$skip_update, results => \@results ); + +##push @results, ProcessTicketStatus(TicketObj => $TicketObj, ARGSRef => \%ARGS); +# for WillResolve +##push @results, ProcessTicketDates( TicketObj => $TicketObj, ARGSRef => \%ARGS); + +{ + my ($status, @msg) = $m->comp( + '/Elements/ValidateCustomFields', + Object => $TicketObj, + CustomFields => $CustomFields, + ARGSRef => \%ARGS, + ); + unless ($status) { + push @results, @msg; + $skip_update = 1; + } +} + +unless ($skip_update) { +## push @results, ProcessTicketBasics(TicketObj => $TicketObj, ARGSRef => \%ARGS); + push @results, ProcessObjectCustomFieldUpdates(Object => $TicketObj, ARGSRef => \%ARGS); + $m->callback( CallbackName => 'ProcessUpdates', TicketObj => $TicketObj, + ARGSRef => \%ARGS, Results => \@results ); + + $TicketObj->ApplyTransactionBatch; + + MaybeRedirectForResults( + Actions => \@results, + Path => "/Ticket/ModifyCustomFieldsPopup.html", + Arguments => { id => $TicketObj->id }, + ); +} + +unless ($TicketObj->CurrentUserHasRight('ShowTicket')) { + if (@results) { + Abort("A change was applied successfully, but you no longer have permissions to view the ticket", Actions => \@results); + } else { + Abort("No permission to view ticket"); + } +} + +</%INIT> +<%ARGS> +$id => undef +</%ARGS> diff --git a/rt/share/html/NoAuth/images/created.png b/rt/share/static/images/created.png Binary files differindex 4d5eeb9ea..4d5eeb9ea 100644 --- a/rt/share/html/NoAuth/images/created.png +++ b/rt/share/static/images/created.png diff --git a/rt/share/html/NoAuth/images/created_due.png b/rt/share/static/images/created_due.png Binary files differindex 52dfc96f0..52dfc96f0 100644 --- a/rt/share/html/NoAuth/images/created_due.png +++ b/rt/share/static/images/created_due.png diff --git a/rt/share/html/NoAuth/images/due.png b/rt/share/static/images/due.png Binary files differindex 30a3aff8a..30a3aff8a 100644 --- a/rt/share/html/NoAuth/images/due.png +++ b/rt/share/static/images/due.png diff --git a/rt/share/html/NoAuth/images/reminder.png b/rt/share/static/images/reminder.png Binary files differindex 4370b6902..4370b6902 100644 --- a/rt/share/html/NoAuth/images/reminder.png +++ b/rt/share/static/images/reminder.png diff --git a/rt/share/html/NoAuth/images/resolved.png b/rt/share/static/images/resolved.png Binary files differindex 09db36d5a..09db36d5a 100644 --- a/rt/share/html/NoAuth/images/resolved.png +++ b/rt/share/static/images/resolved.png diff --git a/rt/share/html/NoAuth/images/started.png b/rt/share/static/images/started.png Binary files differindex e177addea..e177addea 100644 --- a/rt/share/html/NoAuth/images/started.png +++ b/rt/share/static/images/started.png diff --git a/rt/share/html/NoAuth/images/starts.png b/rt/share/static/images/starts.png Binary files differindex 88064ba50..88064ba50 100644 --- a/rt/share/html/NoAuth/images/starts.png +++ b/rt/share/static/images/starts.png diff --git a/rt/share/html/NoAuth/images/starts_due.png b/rt/share/static/images/starts_due.png Binary files differindex 16a4de46f..16a4de46f 100644 --- a/rt/share/html/NoAuth/images/starts_due.png +++ b/rt/share/static/images/starts_due.png diff --git a/rt/share/html/NoAuth/images/updated.png b/rt/share/static/images/updated.png Binary files differindex 680e79a54..680e79a54 100644 --- a/rt/share/html/NoAuth/images/updated.png +++ b/rt/share/static/images/updated.png diff --git a/rt/share/html/NoAuth/images/week-collapse.gif b/rt/share/static/images/week-collapse.gif Binary files differindex 54a123f88..54a123f88 100644 --- a/rt/share/html/NoAuth/images/week-collapse.gif +++ b/rt/share/static/images/week-collapse.gif diff --git a/rt/share/html/NoAuth/images/week-collapse.xcf b/rt/share/static/images/week-collapse.xcf Binary files differindex cbb2b95eb..cbb2b95eb 100644 --- a/rt/share/html/NoAuth/images/week-collapse.xcf +++ b/rt/share/static/images/week-collapse.xcf diff --git a/rt/share/html/NoAuth/images/week-expand.gif b/rt/share/static/images/week-expand.gif Binary files differindex d0f42e9a6..d0f42e9a6 100644 --- a/rt/share/html/NoAuth/images/week-expand.gif +++ b/rt/share/static/images/week-expand.gif diff --git a/rt/share/html/NoAuth/images/week-expand.xcf b/rt/share/static/images/week-expand.xcf Binary files differindex 1ab8e65c8..1ab8e65c8 100644 --- a/rt/share/html/NoAuth/images/week-expand.xcf +++ b/rt/share/static/images/week-expand.xcf |