diff --git a/code/controllers/subsystem/tickets/SStickets.dm b/code/controllers/subsystem/tickets/SStickets.dm
index 2949d9b6bfe..a9bec34fdec 100644
--- a/code/controllers/subsystem/tickets/SStickets.dm
+++ b/code/controllers/subsystem/tickets/SStickets.dm
@@ -37,6 +37,9 @@ SUBSYSTEM_DEF(tickets)
// Autoresponse keys, in sorted order.
var/sorted_responses
+ /// Who has what tickets open? Maps client -> open ticket number.
+ var/list/open_detail_uis = list()
+
/datum/controller/subsystem/tickets/get_metrics()
. = ..()
var/list/cust = list()
@@ -79,7 +82,7 @@ SUBSYSTEM_DEF(tickets)
var/report
for(var/num in stales)
report += "[num], "
- message_staff("Tickets [report] have been open for over [TICKET_TIMEOUT / 600] minutes. Changing status to stale.")
+ message_staff("Tickets [report] have been open for over [TICKET_TIMEOUT / (60 SECONDS)] minutes. Changing status to stale.")
/datum/controller/subsystem/tickets/get_stat_details()
return "Tickets: [LAZYLEN(allTickets)]"
@@ -206,11 +209,18 @@ SUBSYSTEM_DEF(tickets)
to_chat_safe(returnClient(N), "Your [ticket_name] has now been resolved.")
return TRUE
+/datum/controller/subsystem/tickets/proc/refresh_tickets(list/tickets)
+ for(var/datum/ticket/T in tickets)
+ for(var/client/client in open_detail_uis)
+ if(client && open_detail_uis[client] == T.ticketNum)
+ showDetailUI(client.mob, T.ticketNum)
+
/datum/controller/subsystem/tickets/proc/addResponse(list/tickets, who, message)
var/list/ticket_numbers = list()
for(var/datum/ticket/T in tickets)
ticket_numbers += T.ticketNum
T.addResponse(who, message)
+ refresh_tickets(tickets)
if(length(ticket_numbers) == 1)
for(var/datum/ticket/only_ticket in tickets)
@@ -532,9 +542,11 @@ UI STUFF
/datum/controller/subsystem/tickets/proc/showUI(mob/user, tab)
var/dat = null
dat = returnUI(tab)
- var/datum/browser/popup = new(user, ticket_system_name, ticket_system_name, 1400, 600)
+ var/datum/browser/popup = new(user, ticket_system_name, ticket_system_name, 1400, 800)
popup.set_content(dat)
popup.open()
+ // This isn't the detail tab, stop listening for the user's typing.
+ open_detail_uis -= user.client
/datum/controller/subsystem/tickets/proc/showDetailUI(mob/user, ticketID)
var/datum/ticket/T = allTickets[ticketID]
@@ -548,7 +560,8 @@ UI STUFF
dat += "
[T.client_ckey] / [T.mobControlled] opened this [ticket_name] at [T.ingame_time_opened] at location [T.locationSent]
"
dat += "Ticket Status: [status]"
- dat += "
"
+ dat += ""
+ dat += "
"
dat += "| [makeUrlMessage(T, one_line = TRUE)] |
"
if(length(T.ticket_responses) > 1)
@@ -556,7 +569,28 @@ UI STUFF
var/datum/ticket_response/TR = T.ticket_responses[i]
dat += "| [TR.to_string()] |
"
- dat += "
"
+ dat += "
"
+ var/client/C = get_client_by_ckey(T.client_ckey)
+ for(var/key in C?.pm_tracker.pms)
+ var/datum/pm_convo/convo = C.pm_tracker.pms[key]
+ if(convo.typing)
+ dat += "[T.client_ckey] is typing
"
+ break
+
+ for(var/client/X in GLOB.admins)
+ if(ckey(X.ckey) == ckey(T.client_ckey))
+ continue
+ if(!check_rights_for(X, rights_needed))
+ continue
+ for(var/key in X.pm_tracker.pms)
+ if(ckey(key) != ckey(T.client_ckey))
+ continue
+ var/datum/pm_convo/convo = X.pm_tracker.pms[key]
+ if(convo.typing)
+ dat += "[X.ckey] is typing
"
+ break
+
+ dat += "
"
dat += "Re-Open[check_rights(rights_needed, 0) ? "Auto": ""]Resolve
"
if(!T.staffAssigned)
@@ -574,9 +608,19 @@ UI STUFF
dat += "Close Ticket"
dat += "Convert Ticket"
- var/datum/browser/popup = new(user, "[ticket_system_name]detail", "[ticket_system_name] #[T.ticketNum]", 1000, 600)
+ var/datum/browser/popup = new(user, "[ticket_system_name]detail", "[ticket_system_name] #[T.ticketNum]", 1000, 800, src)
+ popup.add_head_content(@{""})
popup.set_content(dat)
popup.open()
+ open_detail_uis[user.client] = T.ticketNum
+
+/datum/controller/subsystem/tickets/proc/onCloseDetailUI(mob/user)
+ open_detail_uis -= user.client
/datum/controller/subsystem/tickets/proc/userDetailUI(mob/user)
//dat
@@ -591,7 +635,7 @@ UI STUFF
dat += "| [TR.to_string()] |
"
dat += ""
- var/datum/browser/popup = new(user, "[ticket_system_name]userticketsdetail", ticket_system_name, 1000, 600)
+ var/datum/browser/popup = new(user, "[ticket_system_name]userticketsdetail", ticket_system_name, 1000, 800)
popup.set_content(dat)
popup.open()
@@ -697,6 +741,9 @@ UI STUFF
else
usr.client.resolveAllAdminTickets()
+ if(href_list["close"])
+ onCloseDetailUI(usr)
+
/datum/controller/subsystem/tickets/proc/takeTicket(index)
if(assignStaffToTicket(usr.client, index))
if(span_class == "mentorhelp")
diff --git a/code/modules/admin/verbs/adminpm.dm b/code/modules/admin/verbs/adminpm.dm
index 1ee1e1ad547..f094b4d9644 100644
--- a/code/modules/admin/verbs/adminpm.dm
+++ b/code/modules/admin/verbs/adminpm.dm
@@ -86,28 +86,6 @@
if(alert("That player has been PM'd in the last [config.simultaneous_pm_warning_timeout / 10] seconds by: [C.ckey_last_pm]","Simultaneous PMs warning","Continue","Cancel") == "Cancel")
return*/
- //get message text, limit it's length.and clean/escape html
- if(!msg)
- set_typing(C, TRUE)
- msg = clean_input("Message:", "Private message to [holder ? key_name(C, FALSE) : key_name_hidden(C, FALSE)]", null, src)
- set_typing(C, FALSE)
-
- if(!msg)
- return
- if(!C)
- if(holder)
- to_chat(src, "Error: Admin-PM: Client not found.")
- else
- adminhelp(msg) //admin we are replying to has vanished, adminhelp instead
- return
-
- if(handle_spam_prevention(msg, MUTE_ADMINHELP, OOC_COOLDOWN))
- return
-
- // Let high-rank admins use advanced pencode.
- if(check_rights(R_SERVER|R_DEBUG, 0))
- msg = admin_pencode_to_html(msg)
-
var/send_span
var/receive_span
var/send_pm_type = " "
@@ -127,6 +105,41 @@
message_type = MESSAGE_TYPE_ADMINPM
tickets_system = SStickets
+ //Check if the mob being PM'd has any open tickets.
+ var/list/tickets = tickets_system.checkForTicket(C, ticket_id)
+ if(!length(tickets))
+ // If we didn't find a specific ticket by the target mob, we check for
+ // tickets by the source mob.
+ if(message_type == MESSAGE_TYPE_MENTORPM)
+ if(check_rights(R_ADMIN|R_MOD|R_MENTOR, 0, C.mob))
+ tickets = SSmentor_tickets.checkForTicket(src)
+ else
+ if(check_rights(R_ADMIN|R_MOD, 0, C.mob))
+ tickets = SStickets.checkForTicket(src)
+
+ //get message text, limit it's length.and clean/escape html
+ if(!msg)
+ set_typing(C, TRUE)
+ tickets_system.refresh_tickets(tickets)
+ msg = clean_input("Message:", "Private message to [holder ? key_name(C, FALSE) : key_name_hidden(C, FALSE)]", null, src)
+ set_typing(C, FALSE)
+
+ if(!msg)
+ tickets_system.refresh_tickets(tickets)
+ return
+ if(!C)
+ if(holder)
+ to_chat(src, "Error: Admin-PM: Client not found.")
+ else
+ adminhelp(msg) //admin we are replying to has vanished, adminhelp instead
+ return
+
+ if(handle_spam_prevention(msg, MUTE_ADMINHELP, OOC_COOLDOWN))
+ return
+
+ // Let high-rank admins use advanced pencode.
+ if(check_rights(R_SERVER|R_DEBUG, 0))
+ msg = admin_pencode_to_html(msg)
if(holder)
//PMs sent from admins and mods display their rank
@@ -224,22 +237,6 @@
if(check_rights(R_ADMIN|R_MOD, 0, X.mob))
to_chat(X, third_party_message, MESSAGE_TYPE_ADMINPM)
- //Check if the mob being PM'd has any open tickets.
- var/list/tickets = tickets_system.checkForTicket(C, ticket_id)
-
- if(length(tickets))
- tickets_system.addResponse(tickets, src, msg)
- return
-
- // If we didn't find a specific ticket by the target mob, we check for
- // tickets by the source mob.
- if(message_type == MESSAGE_TYPE_MENTORPM)
- if(check_rights(R_ADMIN|R_MOD|R_MENTOR, 0, C.mob))
- tickets = SSmentor_tickets.checkForTicket(src)
- else
- if(check_rights(R_ADMIN|R_MOD, 0, C.mob))
- tickets = SStickets.checkForTicket(src)
-
if(length(tickets))
tickets_system.addResponse(tickets, src, msg)
@@ -288,7 +285,8 @@
return
var/datum/pm_convo/convo = target.pm_tracker.pms[key]
if(!convo)
- return
+ convo = new /datum/pm_convo(src)
+ target.pm_tracker.pms[key] = convo
convo.typing = value
if(target.pm_tracker.open && target.pm_tracker.current_title == key)
target.pm_tracker.show_ui(target.mob)