Previous Page
Next Page

12.10. Ticket-Editor Component

The ticket-editor component provides a form that is used to edit tickets. It allows you to update the ticket's title and description, assign it to a user, and change its status. It also shows some details, including who opened the ticket and when it was last changed. The ticket-editing interface is created by TicketEditor.php (see Listing 12-17) and is shown in Figure 12-13.

Figure 12-13. Ticket editor


Listing 12-17. TicketEditor.php

1 <div id="ticket" class="section">
2 <form id="tForm" onsubmit="return updateTicket(this)">
3   <p id="ticketMessage" class="message"></p>
4
5   <p><label>Ticket ID:</label>
6   <b><span id="ticketId"></span></b>
7   </p>
8

9   <p><label>Title:</label><br>
10  <input name="title">
11  </p>
12
13  <p><label>Description:</label><br>
14  <textarea name="description" rows=6></textarea>
15  </p>
16
17  <p><label>Opened by:</label>
18  <b><span id="openedBy"></span></b>
19  </p>
20
21  <p><label>Assigned to:</label>
22  <select name="assigned">
23    <option>Not Assigned</option>
24  </select>
25  </p>
26
27  <p><label>Status:</label>
28  <select name="status">
29    <option>new</option>
30    <option>assigned</option>
31    <option>open</option>
32    <option>fixed</option>
33  </select>
34  </p>
35
36  <p><label>Last Changed on:</label>
37  <b><span id="lastChanged"></span></b>
38  </p>
39
40  <p><input name="submit" type="submit"
41    value="Update Ticket"></p>
42  <input type="hidden" name="ticket_id" value="">
43 </form>
44 </div>

The ticket editor contains a larger form than the other components in the application, but from an HTML standpoint, it is not any more complex. When the form is submitted, it will run the updateTicket function (line 2), which performs the AJAX submission. The form contains a message target, which will be used to give the user feedback (line 3). The form also contains a number of spans, which will have their innerHTML updated to show static information (lines 6 and 37). The other new element of the form is the addition of a select element that will be dynamically updated with the users in the system (lines 2224). The matching JavaScript is shown in Listing 12-18.

Listing 12-18. TicketEditor.js

1 var tCallback = {
2   getTicket: function(result) {
3     updateTicketForm(result);
4   },
5   updateTicket: function(result) {
6     updateTicketForm(result);
7     setMessage(byId('ticketMessage'),
8       'Ticket Updated');
9     new Effect.Highlight('tForm');
10  }
11 }
12
13 var rTicket = new Ticket(tCallback);
14
15 function viewTicket(id) {
16   selectSection('ticket');
17   rTicket.getTicket(id);
18 }
19
20 function viewTicketForm(form) {
21   viewTicket(form.elements.id.value);
22   return false;
23 }
24
25 function updateTicket(form) {
26   var fields = {};
27   fields.title = form.elements.title.value;
28   fields.description = form.elements.description.value;
29
30   var a = form.elements.assigned;
31  if (a.selectedIndex > 0) {
32     fields.assigned =
33      a.value;
34  }
35 else {
36    fields.assigned = false;
37  }
38
39  var s = form.elements.status;
40  fields.status = s.options.value;
41
42   rTicket.updateTicket(form.elements.ticket_id.value,
43     fields);
44
45   return false;
46 }
47
48 function updateTicketForm(values) {
49   if (!values) {
50   setMessage(byId('frontMessage'),
51      "Ticket doesn't exists");
52    selectSection('front');
53    return;
54  }
55
56  var t = values.ticket;
57  var form = byId('tForm');
58  form.elements.title.value = t.title;
59  form.elements.description.value = t.description;
60  form.elements.ticket_id.value = t.ticket_id;
61
62  byId('lastChanged').innerHTML = t.last_change;
63  byId('openedBy').innerHTML = t.creator;
64  byId('ticketId').innerHTML = t.ticket_id;
65
66  var status = form.elements.status;
67  for(var i = 0; i < status.options.length; i++) {
68    if (status.options[i].text == t.status) {
69      status.selectedIndex = i;
70      break;
71    }
72 }
73
74   // remove current user options
75  var a = form.elements.assigned;
76
77   for(var i = 1; i < a.options.length; i++) {
78     a.remove(i);
79 }
80
81  // add users
82  var u = values.users;
83  for(var i in u) {
84    var o = new Option(u[i],i);
85    a.options[a.options.length] = o;
86 }
87
88  // select user
89  if (t.assigned) {
90    for(var i = 0; i < a.options.length; i++) {
91      if (a.options[i].value
92        == t.assigned) {
93        a.selectedIndex = i;
94        break;
95      }
96    }

97  }
98  else {
99    a.selectedIndex = 0;
100 }
101
102  if (!app.isLoggedIn) {
103   form.submit.value = "Login to Update";
104    form.submit.disabled = true;
105  }
106  else {
107    form.submit.value = "Update Ticket";
108    form.submit.disabled = false;
109  }
110 }

This component doesn't require setup methods, but it does have to set up its AJAX class (line 12). We will be using two of the server's methodsgetTicket and updateTicketso callback functions are added for each. The getTicket callback calls the updateTicketForm method when it is called, and the updateTicket method calls that same method. We will also be providing a user feedback message and highlighting the form (lines 79).

Lines 2023 define the viewTicket method; this is used by other parts of the application, such as the add ticket component, to select a ticket to view. This method sets the current section to ticket and does an AJAX call to getTicket. The viewTicketForm method (lines 2023) calls viewTicket, getting the value of ticket_id from the form that is passed in.

The updateTicket function (lines 2546) processes a submission of the ticket form. It builds an object that contains the fields to update and then makes an AJAX call to updateTicket (line 42) with that list. The fields object is defined on line 26, and then the easy fields (title and description) are added to it. Next the assigned value is processed (lines 3037); assigned is set using a select box, and its first option needs a special value. We support this value mapping by checking the select box's selected index (line 31), and if the first option is not selected, using its value. Otherwise, the mapping code uses the value of false. Setting the assigned property to false lets the back end know that the ticket is unassigned and allows it to clean up the database accordingly. Finishing the process, the status property is added to the fields object (line 40), and the AJAX update is performed.

The updateTicketForm function updates the form that is used to edit the data. It starts with some basic error checking (lines 4954). If the server isn't able to find a ticket for a given ID, it returns false. Thus, the function checks for a false value, sets an error message if it finds one, and then sets the application to the front page. If the ticket exists, we start updating the form. We start with the input boxes, text area, and spans (lines 5864) and then move on to the select boxes. Status contains a hard-coded set of options, so it can be selected by looping over the list, matching the status value against the options text, and then setting the element's selectedIndex property (lines 6672).

The users array is dynamic, so the process has to start by updating the list of users from the data that is returned from the server. This is done by creating a new Option instance for each user and adding it to the select element options array. With the list updated, we loop over the list as we did in the status case. The only difference is that this time, we compare the option's value because we have a user_id. If no user matches, the selected index is set to 0, which is the "not assigned" option.

The function finishes by doing a basic security check. If the user is not logged in, the Submission button is disabled, and a message telling the user to log in to update the ticket is shown. This check allows the same page to be used for authenticated and nonauthenticated users. Like any other security check, this code on the client is there just to provide a good user experience; the back end also enforces security and would prevent any not-logged-in user from updating a ticket, no matter what he or she did to the client's code.


Previous Page
Next Page