Add ability to change ticket urgency
jdarwood007

jdarwood007 commited on 2019-02-17 17:59:03
Showing 6 changed files, with 203 additions and 21 deletions.

... ...
@@ -72,7 +72,7 @@
72 72
 	padding: 0 4px 0 7px;
73 73
 }
74 74
 
75
-dd#assigned_button {
75
+dd#urgency_button, dd#assigned_button {
76 76
 	padding: 1px 0;
77 77
 }
78 78
 
... ...
@@ -104,7 +104,7 @@ h3.ticketheader img {
104 104
 /* Ticket details (Left-floated box) */
105 105
 .shd_ticket_side_column {
106 106
 	float: left;
107
-	width: 20%;
107
+	width: 23%;
108 108
 	padding: 0 5px 5px 5px;
109 109
 }
110 110
 .shd_ticketdetails {
... ...
@@ -137,7 +137,7 @@ form#postmodify .shd_ticket_roundframe {
137 137
 	min-height: 250px;
138 138
 }
139 139
 .shd_ticket_description {
140
-	margin-left: 260px;
140
+	margin-left: 23%;
141 141
 }
142 142
 
143 143
 #shd_ticket_text {
... ...
@@ -34,19 +34,19 @@ function shd_sendJSONDocument(sUrl, funcCallback)
34 34
 /* The privacy toggle in AJAX */
35 35
 function shd_privacyControl(oOpts)
36 36
 {
37
-	this.opts = oOpts; // attaches to the link, but it doesn't exist until after DOM is loaded!
37
+	this.opt = oOpts; // attaches to the link, but it doesn't exist until after DOM is loaded!
38 38
 	$(document).ready(this.init.bind(this));
39 39
 }
40 40
 
41 41
 shd_privacyControl.prototype.init = function ()
42 42
 {
43
-	$('#' + this.opts.sSrcA).on('click', this.action.bind(this));
43
+	$('#' + this.opt.sSrcA).on('click', this.action.bind(this));
44 44
 }
45 45
 
46 46
 shd_privacyControl.prototype.action = function (e)
47 47
 {
48 48
 	e.preventDefault();
49
-	shd_getJSONDocument(this.opts.sUrl + ';' + this.opts.sSession, this.callback.bind(this));
49
+	shd_getJSONDocument(this.opt.sUrl + ';' + this.opt.sSession, this.callback.bind(this));
50 50
 	return false;
51 51
 }
52 52
 
... ...
@@ -55,10 +55,10 @@ shd_privacyControl.prototype.callback = function (oRecvd)
55 55
 	if (oRecvd && oRecvd.success === false)
56 56
 		alert(oRecvd.error);
57 57
 	else if (oRecvd && oRecvd.message)
58
-		$('#' + this.opts.sDestSpan).html(oRecvd.message);
58
+		$('#' + this.opt.sDestSpan).html(oRecvd.message);
59 59
 	else
60 60
 		if (confirm(shd_ajax_problem))
61
-			window.location = smf_scripturl + '?action=helpdesk;sa=privacychange;ticket=' + this.opts.ticket + ';' + this.opts.sSession;
61
+			window.location = smf_scripturl + '?action=helpdesk;sa=privacychange;ticket=' + this.opt.ticket + ';' + this.opt.sSession;
62 62
 
63 63
 	return false;
64 64
 }
... ...
@@ -66,23 +66,31 @@ shd_privacyControl.prototype.callback = function (oRecvd)
66 66
 /* The urgency doodad */
67 67
 function shd_urgencyControl(oOpts)
68 68
 {
69
-	this.opts = oOpts; // attaches to the link, but it doesn't exist until after DOM is loaded!
69
+	this.opt = oOpts; // attaches to the link, but it doesn't exist until after DOM is loaded!
70 70
 	$(document).ready(this.init.bind(this));
71 71
 }
72 72
 
73 73
 shd_urgencyControl.prototype.init = function ()
74 74
 {
75
-	for (var i in this.opts.aButtonOps)
75
+	for (var i in this.opt.aButtonOps)
76 76
 	{
77
-		if (!this.opts.aButtonOps.hasOwnProperty(i))
77
+		if (!this.opt.aButtonOps.hasOwnProperty(i))
78 78
 			continue;
79 79
 
80
-		var oDiv = $('#urglink_' + this.opts.aButtonOps[i]);
80
+		var oDiv = $('#urglink_' + this.opt.aButtonOps[i]);
81 81
 		if (oDiv !== null && i == 'up')
82 82
 			oDiv.on('click', this.actionUp.bind(this));
83 83
 		else if (oDiv !== null && i == 'down')
84 84
 			oDiv.on('click', this.actionDown.bind(this)); // I *did* try to make this a single parameterised function but it always fired when it wasn't supposed to
85 85
 	}
86
+
87
+	// Setup the assign by list option.
88
+	this.bCollapsed = true;
89
+	this.opt.sUrlExpand = smf_prepareScriptUrl(smf_scripturl) + 'action=helpdesk;sa=ajax;op=urgencylist;ticket=' + this.opt.iTicketId;
90
+	this.opt.sUrlAssign = smf_prepareScriptUrl(smf_scripturl) + 'action=helpdesk;sa=ajax;op=urgency;assign;ticket=' + this.opt.iTicketId;
91
+	$('#' + this.opt.sSelectButtonId).html('<img src="' + this.opt.sImageCollapsed + '" id="urgency_' + this.opt.sSelf + '" class="shd_urgency_button">');
92
+	$('.shd_ticketdetails').on('click', '#urgency_' + this.opt.sSelf, this.clickList.bind(this));
93
+
86 94
 }
87 95
 
88 96
 shd_urgencyControl.prototype.actionUp = function (e)
... ...
@@ -100,7 +108,7 @@ shd_urgencyControl.prototype.actionDown = function (e)
100 108
 shd_urgencyControl.prototype.action = function (direction)
101 109
 {
102 110
 	this.direction = direction;
103
-	shd_getJSONDocument(this.opts.sUrl + this.opts.aButtonOps[direction] + ';' + this.opts.sSession, this.callback.bind(this));
111
+	shd_getJSONDocument(this.opt.sUrl + this.opt.aButtonOps[direction] + ';' + this.opt.sSession, this.callback.bind(this));
104 112
 	return false;
105 113
 }
106 114
 
... ...
@@ -110,7 +118,7 @@ shd_urgencyControl.prototype.callback = function (oRecvd)
110 118
 		alert(oRecvd.error);
111 119
 	else if (oRecvd && oRecvd.message)
112 120
 	{
113
-		$('#' + this.opts.sDestSpan).html(oRecvd.message);
121
+		$('#' + this.opt.sDestSpan).html(oRecvd.message);
114 122
 
115 123
 		var btn_set = ['increase', 'decrease'];
116 124
 		for (var i in btn_set)
... ...
@@ -127,11 +135,82 @@ shd_urgencyControl.prototype.callback = function (oRecvd)
127 135
 	}
128 136
 	else
129 137
 		if (confirm(shd_ajax_problem))
130
-			window.location = smf_scripturl + '?action=helpdesk;sa=urgencychange;ticket=' + this.opts.ticket + ';change=' + this.opts.aButtonOps[this.direction] + ';' + this.opts.sSession;
138
+			window.location = smf_scripturl + '?action=helpdesk;sa=urgencychange;ticket=' + this.opt.iTicketId + ';change=' + this.opt.aButtonOps[this.direction] + ';' + this.opt.sSession;
131 139
 
132 140
 	return false;
133 141
 }
134 142
 
143
+shd_urgencyControl.prototype.clickList = function ()
144
+{
145
+	if (this.bCollapsed)
146
+		this.expandList();
147
+	else
148
+		this.collapseList();
149
+}
150
+
151
+shd_urgencyControl.prototype.expandList = function ()
152
+{
153
+	this.bCollapsed = false;
154
+console.log('shd_urgencyControl.prototype.expandList:', this.opt.sSelectButtonId, $('#' + this.opt.sSelectButtonId), this.opt.sImageExpanded);
155
+	$('#urgency_' + this.opt.sSelf).attr('src', this.opt.sImageExpanded);
156
+
157
+	// Fetch the list of items
158
+	shd_getJSONDocument(this.opt.sUrlExpand + ';' + this.opt.sSession, this.expandList_callback.bind(this));
159
+}
160
+
161
+shd_urgencyControl.prototype.expandList_callback = function (oRecvd)
162
+{
163
+	if (oRecvd && oRecvd.success === false)
164
+		alert(oRecvd.error);
165
+	else if (oRecvd && oRecvd.urgencies)
166
+	{
167
+		$('#' + this.opt.sSelectListId).show();
168
+
169
+		var newhtml = '';
170
+		var cur = 0;
171
+		for (var i in oRecvd.urgencies)
172
+		{
173
+			if (!oRecvd.urgencies.hasOwnProperty(i))
174
+				continue;
175
+
176
+			cur = oRecvd.urgencies[i];
177
+			selected = cur.selected ? ' selected="selected"' : '';
178
+			newhtml += '<option class="shd_urgencies" data-id="' + cur.id + '"' + selected + '>' + cur.name + '</option>';
179
+		}
180
+
181
+		$('#' + this.opt.sSelectListId).html(newhtml);
182
+		$('#' + this.opt.sSelectListId).on('change', this.assignUrgency.bind(this));
183
+	}
184
+}
185
+
186
+shd_urgencyControl.prototype.assignUrgency = function (e)
187
+{
188
+	// Click handler for the assignment list, to issue the assign
189
+	ajax_indicator(true);
190
+
191
+	var selectedIndex = e.currentTarget.selectedIndex;	
192
+	shd_getJSONDocument(this.opt.sUrlAssign + ';urgency=' + e.currentTarget[selectedIndex].dataset.id + ';'+ this.opt.sSession, this.assignUrgencyCallback.bind(this));
193
+}
194
+
195
+shd_urgencyControl.prototype.assignUrgencyCallback = function(oRecvd)
196
+{
197
+	// Click handler callback for assignment, to handle once the request has been made
198
+	this.collapseList();
199
+
200
+	if (oRecvd && oRecvd.success === false)
201
+		alert(oRecvd.error);
202
+	else if (oRecvd && oRecvd.message)
203
+		document.getElementById(this.opt.sDestSpan).innerHTML = oRecvd.message;
204
+}
205
+
206
+shd_urgencyControl.prototype.collapseList = function ()
207
+{
208
+	this.bCollapsed = true;
209
+	$('#' + this.opt.sSelectListId).hide().html();
210
+	$('#urgency_' + this.opt.sSelf).attr('src', this.opt.sImageCollapsed);
211
+}
212
+
213
+
135 214
 /* Attachment selector, based on http://the-stickman.com/web-development/javascript/upload-multiple-files-with-a-single-file-element/
136 215
 * The code below is modified under the MIT licence, http://the-stickman.com/using-code-from-this-site-ie-licence/ not reproduced here for
137 216
 * convenience of users using this software (as this is an active downloaded file) */
... ...
@@ -224,7 +303,7 @@ shd_attach_select.prototype.addListRow = function (element)
224 303
 	var new_row = document.createElement('div');
225 304
 	var new_row_button = document.createElement('input');
226 305
 	new_row_button.type = 'button';
227
-	new_row_button.value = this.opts.message_txt_delete;
306
+	new_row_button.value = this.opt.message_txt_delete;
228 307
 	new_row_button.className = 'button';
229 308
 	new_row.element = element;
230 309
 
... ...
@@ -240,7 +319,7 @@ shd_attach_select.prototype.addListRow = function (element)
240 319
 
241 320
 	new_row.innerHTML = element.value + '&nbsp; &nbsp;';
242 321
 	new_row.appendChild(new_row_button);
243
-	document.getElementById(this.opts.file_container).appendChild(new_row);
322
+	document.getElementById(this.opt.file_container).appendChild(new_row);
244 323
 };
245 324
 
246 325
 shd_attach_select.prototype.checkActive = function()
... ...
@@ -57,6 +57,7 @@ $txt['shd_log_marknotprivate'] = '&quot;<a href="{scripturl}?action=helpdesk;sa=
57 57
 //@{
58 58
 $txt['shd_log_urgency_increase'] = '&quot;<a href="{scripturl}?action=helpdesk;sa=ticket;ticket={ticket}">{subject}</a>&quot; increased to <strong>{urgency}</strong>.';
59 59
 $txt['shd_log_urgency_decrease'] = '&quot;<a href="{scripturl}?action=helpdesk;sa=ticket;ticket={ticket}">{subject}</a>&quot; decreased to <strong>{urgency}</strong>.';
60
+$txt['shd_log_urgency_change'] = '&quot;<a href="{scripturl}?action=helpdesk;sa=ticket;ticket={ticket}">{subject}</a>&quot; changed to <strong>{urgency}</strong>.';
60 61
 //@}
61 62
 
62 63
 //! @name Ticket/topic, topic/ticket moves
... ...
@@ -59,6 +59,7 @@ function shd_ajax()
59 59
 	$subactions = array(
60 60
 		'privacy' => 'shd_ajax_privacy',
61 61
 		'urgency' => 'shd_ajax_urgency',
62
+		'urgencylist' => 'shd_ajax_urgencylist',
62 63
 		'quote' => 'shd_ajax_quote',
63 64
 		'assign' => 'shd_ajax_assign',
64 65
 		'assign2' => 'shd_ajax_assign2',
... ...
@@ -223,6 +224,22 @@ function shd_ajax_urgency()
223 224
 	if (empty($row))
224 225
 		return array('error' => $txt['shd_no_ticket']);
225 226
 
227
+	// We will need this later.
228
+	require_once($sourcedir . '/sd_source/Subs-SimpleDeskPost.php');
229
+
230
+	// If being assigned from the list, we do it differently.
231
+	if (isset($_GET['assign']) && isset($_GET['urgency']) && ctype_digit($_GET['urgency']))
232
+	{
233
+		shd_get_urgency_options($row['id_member_started'] == $user_info['id'], $row['id_dept']);
234
+
235
+		if (empty($context['ticket_form']['urgency']['options'][$_GET['urgency']]))
236
+			return array('success' => false, 'error' => $txt['shd_cannot_change_urgency']);
237
+
238
+		$new_urgency = (int) $_GET['urgency'];
239
+		$action = 'urgency_change';
240
+	}
241
+	else
242
+	{
226 243
 		$can_urgency = shd_can_alter_urgency($row['urgency'], $row['id_member_started'], ($row['status'] == TICKET_STATUS_CLOSED), ($row['status'] == TICKET_STATUS_DELETED), $row['id_dept']);
227 244
 
228 245
 		if (empty($_GET['change']) || empty($can_urgency[$_GET['change']]))
... ...
@@ -230,8 +247,9 @@ function shd_ajax_urgency()
230 247
 
231 248
 		$new_urgency = $row['urgency'] + ($_GET['change'] == 'increase' ? 1 : -1);
232 249
 		$action = 'urgency_' . $_GET['change'];
250
+	}
233 251
 
234
-	require_once($sourcedir . '/sd_source/Subs-SimpleDeskPost.php');
252
+	// Build the modify information.
235 253
 	$msgOptions = array();
236 254
 	$posterOptions = array();
237 255
 	$ticketOptions = array(
... ...
@@ -266,6 +284,79 @@ function shd_ajax_urgency()
266 284
 	return $context['ajax_return'];
267 285
 }
268 286
 
287
+/**
288
+ *	Handles AJAX updates to ticket urgency list.
289
+ *
290
+ *	Operations:
291
+ *	- silent session check; if fail, add to $context['ajax_return']['error']
292
+ *	- ticket id check; if fail, add to $context['ajax_return']['error']
293
+ *	- get enough ticket data to do this
294
+ *	- check permissions with {@link shd_can_alter_urgency()} and permissions; if fail, add to $context['ajax_return']['error']
295
+ *	- identify whether the new urgency needs 'urgent' styling or not and put the new urgency in $context['ajax_return']['message']
296
+ *	- update the database with the new urgency
297
+ *	- identify whether the new urgency continues to allow the current user to change urgency or not
298
+ *	- put the button links if appropriate into $context['ajax_return']['increase'] and $context['ajax_return']['decrease'] and return
299
+ *
300
+ *	@return array Response data for Ajax.
301
+ *  @since 2.1
302
+*/
303
+function shd_ajax_urgencylist()
304
+{
305
+	global $smcFunc, $user_info, $context, $txt, $scripturl, $settings, $sourcedir;
306
+
307
+	$session_check = checkSession('get', '', false); // check the session but don't die fatally.
308
+	if (!empty($session_check))
309
+		return array('success' => false, 'error' => $txt[$session_check]);
310
+
311
+	// First, figure out the state of the ticket - is it private or not? Can we even see it?
312
+	if (empty($context['ticket_id']))
313
+		return array('success' => false, 'error' => $txt['shd_no_ticket']);
314
+
315
+	$query = shd_db_query('', '
316
+		SELECT id_member_started, subject, urgency, status, id_dept
317
+		FROM {db_prefix}helpdesk_tickets AS hdt
318
+		WHERE {query_see_ticket}
319
+			AND id_ticket = {int:current_ticket}',
320
+		array(
321
+			'current_ticket' => $context['ticket_id'],
322
+		)
323
+	);
324
+
325
+	$row = $smcFunc['db_fetch_assoc']($query);
326
+	$smcFunc['db_free_result']($query);
327
+
328
+	// No ticket, no luck.
329
+	if (empty($row))
330
+		return array('error' => $txt['shd_no_ticket']);
331
+
332
+	// Build the list.
333
+	$context['ajax_return'] = array(
334
+		'success' => true,
335
+		'urgencies' => array(),
336
+	);
337
+
338
+	// Get the options.
339
+	require_once($sourcedir . '/sd_source/Subs-SimpleDeskPost.php');
340
+	shd_get_urgency_options($row['id_member_started'] == $user_info['id'], $row['id_dept']);
341
+
342
+	foreach($context['ticket_form']['urgency']['options'] as $urgency => $urgency_txt)
343
+	{
344
+		$can_urgency = shd_can_alter_urgency($urgency, $row['id_member_started'], ($row['status'] == TICKET_STATUS_CLOSED), ($row['status'] == TICKET_STATUS_DELETED), $row['id_dept']);
345
+
346
+		// Can't do this either way? Don't show this as a option.
347
+		if (empty($can_urgency['increase']) && empty($can_urgency['decrease']))
348
+			continue;
349
+
350
+		$context['ajax_return']['urgencies'][$urgency] = array(
351
+			'id' => $urgency,
352
+			'name' => $txt[$urgency_txt],
353
+			'selected' => $row['urgency'] == $urgency,
354
+		);
355
+	}
356
+	
357
+	return $context['ajax_return'];
358
+}
359
+
269 360
 /**
270 361
  *	Collects ticket post data for quoting posts through AJAX (i.e. inserting a quote live into the postbox)
271 362
  *
... ...
@@ -451,6 +451,7 @@ function shd_log_action($action, $params, $do_last_update = true)
451 451
 		'marknotprivate' => 'shd_logopt_privacy',
452 452
 		'urgency_increase' => 'shd_logopt_urgency',
453 453
 		'urgency_decrease' => 'shd_logopt_urgency',
454
+		'urgency_change' => 'shd_logopt_urgency',
454 455
 		'tickettotopic' => 'shd_logopt_tickettopicmove',
455 456
 		'topictoticket' => 'shd_logopt_tickettopicmove',
456 457
 		'delete' => 'shd_logopt_delete',
... ...
@@ -69,7 +72,12 @@ function template_viewticket()
69 72
 						<dd id="item_urgency"><span id="urgency">', $context['ticket']['urgency']['label'], '</span>
70 73
 							<span id="urgency_increase">', (!empty($context['ticket']['urgency']['increase']) ? '<a id="urglink_increase" href="' . $scripturl . '?action=helpdesk;sa=urgencychange;ticket=' . $context['ticket']['id'] . ';change=increase;' . $context['session_var'] . '=' . $context['session_id'] . '" title="' . $txt['shd_urgency_increase'] . '"><span class="generic_icons urgency_increase" title="' . $txt['shd_urgency_increase'] . '"></span></a>' : ''), '</span>
71 74
 							<span id="urgency_decrease">', (!empty($context['ticket']['urgency']['decrease']) ? '<a id="urglink_decrease" href="' . $scripturl . '?action=helpdesk;sa=urgencychange;ticket=' . $context['ticket']['id'] . ';change=decrease;' . $context['session_var'] . '=' . $context['session_id'] . '" title="' . $txt['shd_urgency_decrease'] . '"><span class="generic_icons urgency_decrease" title="' . $txt['shd_urgency_decrease'] . '"></span></a>' : ''), '</span>
75
+							<span id="urgency_button"></span>
76
+						</dd>
77
+						<dd class="shd_urgency_list">
78
+							<select id="urgency_list" class="hidden"></select>
72 79
 						</dd>
80
+
73 81
 						<dt><img src="', $settings['default_images_url'], '/simpledesk/staff.png" alt="" class="shd_smallicon"> ', $txt['shd_ticket_assignedto'], ':</dt>
74 82
 						<dd><span id="assigned_to">', $context['ticket']['assigned']['link'], '</span><span id="assigned_button"></span></dd>
75 83
 						<dt class="shd_assignees_list">
... ...
@@ -1073,16 +1083,21 @@ function template_shd_js_privacy()
1073 1083
 */
1074 1084
 function template_shd_js_urgency()
1075 1085
 {
1076
-	global $context;
1086
+	global $context, $settings;
1077 1087
 
1078 1088
 	echo '
1079 1089
 		var urgencyCtl = new shd_urgencyControl({
1080
-			ticket: ', $context['ticket_id'], ',
1090
+			sSelf: "urgencyCtl",
1091
+			iTicketId: ' . $context['ticket_id'] . ',
1081 1092
 			sUrl: smf_scripturl + "?action=helpdesk;sa=ajax;op=urgency;ticket=', $context['ticket_id'], ';change=",
1082 1093
 			sSession: smf_session_var + "=" + smf_session_id,
1083 1094
 			sDestSpan: "urgency",
1084 1095
 			aButtons: ["up", "down"],
1085
-			aButtonOps: { up: "increase", down: "decrease" }
1096
+			aButtonOps: {up:"increase", down:"decrease"},
1097
+			sSelectButtonId: "urgency_button",
1098
+			sSelectListId: "urgency_list",
1099
+			sImageCollapsed: ', JavaScriptEscape($settings['default_images_url'] . '/simpledesk/ajax_assign.png'), ',
1100
+			sImageExpanded: ', JavaScriptEscape($settings['default_images_url'] . '/simpledesk/ajax_assign_cancel.png'), ',
1086 1101
 		});';
1087 1102
 }
1088 1103
 
1089 1104