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 += "" if(length(T.ticket_responses) > 1) @@ -556,7 +569,28 @@ UI STUFF var/datum/ticket_response/TR = T.ticket_responses[i] dat += "" - dat += "
[makeUrlMessage(T, one_line = TRUE)]
[TR.to_string()]


" + 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)