From 2baeb1b635e0fa1e31a6ffc267d10b31a1eedffc Mon Sep 17 00:00:00 2001 From: Seth Scherer Date: Fri, 20 May 2022 15:15:32 -0400 Subject: [PATCH] Ports the player ticket panel from skyrat (#66954) * Ports the player ticket panel from skyrat Adds a player side panel to view active admin tickets, this will make it easier for players to find previous admin messages, remember what they said previously etc. This is especially good for the cases that TGchat drops messages --- code/modules/admin/verbs/adminhelp.dm | 115 ++++++++++++++++++++------ code/modules/admin/verbs/adminpm.dm | 18 ++-- code/modules/client/client_procs.dm | 3 + 3 files changed, 103 insertions(+), 33 deletions(-) diff --git a/code/modules/admin/verbs/adminhelp.dm b/code/modules/admin/verbs/adminhelp.dm index 09f99aa8f38..ac7cdcc4646 100644 --- a/code/modules/admin/verbs/adminhelp.dm +++ b/code/modules/admin/verbs/adminhelp.dm @@ -195,6 +195,8 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new) var/list/opening_responders /// Whether this ahelp has sent a webhook or not, and what type var/webhook_sent = WEBHOOK_NONE + /// List of player interactions + var/list/player_interactions /** * Call this on its own to create a ticket, don't manually assign current_ticket @@ -228,9 +230,10 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new) statclick = new(null, src) ticket_interactions = list() + player_interactions = list() if(is_bwoink) - AddInteraction("[key_name_admin(usr)] PM'd [LinkedReplyName()]") + AddInteraction("[key_name_admin(usr)] PM'd [LinkedReplyName()]", player_message = "[key_name_admin(usr, include_name = FALSE)] PM'd [LinkedReplyName()]") message_admins("Ticket [TicketHref("#[id]")] created") else MessageNoRecipient(msg_raw, urgent) @@ -342,11 +345,13 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new) GLOB.ahelp_tickets.resolved_tickets -= src return ..() -/datum/admin_help/proc/AddInteraction(formatted_message) +/datum/admin_help/proc/AddInteraction(formatted_message, player_message) if(heard_by_no_admins && usr && usr.ckey != initiator_ckey) heard_by_no_admins = FALSE send2adminchat(initiator_ckey, "Ticket #[id]: Answered by [key_name(usr)]") ticket_interactions += "[time_stamp()]: [formatted_message]" + if (!isnull(player_message)) + player_interactions += "[time_stamp()]: [player_message]" //Removes the ahelp verb and returns it after 2 minutes /datum/admin_help/proc/TimeoutVerb() @@ -392,7 +397,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new) //Message to be sent to all admins var/admin_msg = span_adminnotice(span_adminhelp("Ticket [TicketHref("#[id]", ref_src)]: [LinkedReplyName(ref_src)] [FullMonty(ref_src)]: [keywords_lookup(msg)]")) - AddInteraction("[LinkedReplyName(ref_src)]: [msg]") + AddInteraction("[LinkedReplyName(ref_src)]: [msg]", player_message = "[LinkedReplyName(ref_src)]: [msg]") log_admin_private("Ticket #[id]: [key_name(initiator)]: [msg]") //send this msg to all admins @@ -436,7 +441,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new) if(initiator) initiator.current_ticket = src - AddInteraction("Reopened by [key_name_admin(usr)]") + AddInteraction("Reopened by [key_name_admin(usr)]", player_message = "Ticket reopened!") var/msg = span_adminhelp("Ticket [TicketHref("#[id]")] reopened by [key_name_admin(usr)].") message_admins(msg) log_admin_private(msg) @@ -463,7 +468,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new) RemoveActive() state = AHELP_CLOSED GLOB.ahelp_tickets.ListInsert(src) - AddInteraction("Closed by [key_name].") + AddInteraction("Closed by [key_name].", player_message = "Ticket closed!") if(!silent) SSblackbox.record_feedback("tally", "ahelp_stats", 1, "closed") var/msg = "Ticket [TicketHref("#[id]")] closed by [key_name]." @@ -481,7 +486,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new) addtimer(CALLBACK(initiator, /client/proc/giveadminhelpverb), 50) - AddInteraction("Resolved by [key_name].") + AddInteraction("Resolved by [key_name].", player_message = "Ticket resolved!") to_chat(initiator, span_adminhelp("Your ticket has been resolved by an admin. The Adminhelp verb will be returned to you shortly."), confidential = TRUE) if(!silent) SSblackbox.record_feedback("tally", "ahelp_stats", 1, "resolved") @@ -508,7 +513,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new) var/msg = "Ticket [TicketHref("#[id]")] rejected by [key_name]" message_admins(msg) log_admin_private(msg) - AddInteraction("Rejected by [key_name].") + AddInteraction("Rejected by [key_name].", player_message = "Ticket rejected!") SSblackbox.LogAhelp(id, "Rejected", "Rejected by [usr.key]", null, usr.ckey) Close(silent = TRUE) @@ -527,7 +532,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new) msg = "Ticket [TicketHref("#[id]")] marked as IC by [key_name]" message_admins(msg) log_admin_private(msg) - AddInteraction("Marked as IC issue by [key_name]") + AddInteraction("Marked as IC issue by [key_name]", player_message = "Marked as IC issue!") SSblackbox.LogAhelp(id, "IC Issue", "Marked as IC issue by [usr.key]", null, usr.ckey) Resolve(silent = TRUE) @@ -622,6 +627,32 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new) if("reopen") Reopen() +/datum/admin_help/proc/player_ticket_panel() + var/list/dat = list("Player Ticket") + dat += "State: " + switch(state) + if(AHELP_ACTIVE) + dat += "OPEN" + if(AHELP_RESOLVED) + dat += "RESOLVED" + if(AHELP_CLOSED) + dat += "CLOSED" + else + dat += "UNKNOWN" + dat += "\n[FOURSPACES]Refresh" + dat += "

Opened at: [gameTimestamp("hh:mm:ss", opened_at)] (Approx [DisplayTimeText(world.time - opened_at)] ago)" + if(closed_at) + dat += "
Closed at: [gameTimestamp("hh:mm:ss", closed_at)] (Approx [DisplayTimeText(world.time - closed_at)] ago)" + dat += "

" + dat += "
Log:

" + for (var/interaction in player_interactions) + dat += "[interaction]
" + + var/datum/browser/player_panel = new(usr, "ahelp[id]", 0, 620, 480) + player_panel.set_content(dat.Join()) + player_panel.open() + + // // TICKET STATCLICK // @@ -752,34 +783,68 @@ GLOBAL_DATUM_INIT(admin_help_ui_handler, /datum/admin_help_ui_handler, new) GLOB.admin_help_ui_handler.ui_interact(mob) to_chat(src, span_boldnotice("Adminhelp failing to open or work? Click here")) +/client/verb/view_latest_ticket() + set category = "Admin" + set name = "View Latest Ticket" + + if(!current_ticket) + // Check if the client had previous tickets, and show the latest one + var/list/prev_tickets = list() + var/datum/admin_help/last_ticket + // Check all resolved tickets for this player + for(var/datum/admin_help/resolved_ticket in GLOB.ahelp_tickets.resolved_tickets) + if(resolved_ticket.initiator_ckey == ckey) // Initiator is a misnomer, it's always the non-admin player even if an admin bwoinks first + prev_tickets += resolved_ticket + // Check all closed tickets for this player + for(var/datum/admin_help/closed_ticket in GLOB.ahelp_tickets.closed_tickets) + if(closed_ticket.initiator_ckey == ckey) + prev_tickets += closed_ticket + // Take the most recent entry of prev_tickets and open the panel on it + if(LAZYLEN(prev_tickets)) + last_ticket = pop(prev_tickets) + last_ticket.player_ticket_panel() + return + + // client had no tickets this round + to_chat(src, span_warning("You have not had an ahelp ticket this round.")) + return + + current_ticket.player_ticket_panel() // // LOGGING // -//Use this proc when an admin takes action that may be related to an open ticket on what -//what can be a client, ckey, or mob -//log_in_blackbox: Whether or not this message with the blackbox system. -//If disabled, this message should be logged with a different proc call -/proc/admin_ticket_log(what, message, log_in_blackbox = TRUE) - var/client/C +/// Use this proc when an admin takes action that may be related to an open ticket on what +/// what can be a client, ckey, or mob +/// player_message: If the message should be shown in the player ticket panel, fill this out +/// log_in_blackbox: Whether or not this message with the blackbox system. +/// If disabled, this message should be logged with a different proc call +/proc/admin_ticket_log(what, message, player_message, log_in_blackbox = TRUE) + var/client/mob_client var/mob/Mob = what if(istype(Mob)) - C = Mob.client + mob_client = Mob.client else - C = what - if(istype(C) && C.current_ticket) - C.current_ticket.AddInteraction(message) + mob_client = what + if(istype(mob_client) && mob_client.current_ticket) + if (isnull(player_message)) + mob_client.current_ticket.AddInteraction(message) + else + mob_client.current_ticket.AddInteraction(message, player_message) if(log_in_blackbox) - SSblackbox.LogAhelp(C.current_ticket.id, "Interaction", message, C.ckey, usr.ckey) - return C.current_ticket + SSblackbox.LogAhelp(mob_client.current_ticket.id, "Interaction", message, mob_client.ckey, usr.ckey) + return mob_client.current_ticket if(istext(what)) //ckey - var/datum/admin_help/AH = GLOB.ahelp_tickets.CKey2ActiveTicket(what) - if(AH) - AH.AddInteraction(message) + var/datum/admin_help/active_admin_help = GLOB.ahelp_tickets.CKey2ActiveTicket(what) + if(active_admin_help) + if (isnull(player_message)) + active_admin_help.AddInteraction(message) + else + active_admin_help.AddInteraction(message, player_message) if(log_in_blackbox) - SSblackbox.LogAhelp(AH.id, "Interaction", message, what, usr.ckey) - return AH + SSblackbox.LogAhelp(active_admin_help.id, "Interaction", message, what, usr.ckey) + return active_admin_help // // HELPER PROCS diff --git a/code/modules/admin/verbs/adminpm.dm b/code/modules/admin/verbs/adminpm.dm index 0fb00e2ec69..44688da482b 100644 --- a/code/modules/admin/verbs/adminpm.dm +++ b/code/modules/admin/verbs/adminpm.dm @@ -214,9 +214,9 @@ type = MESSAGE_TYPE_ADMINPM, html = span_notice("PM to-Admins: [rawmsg]"), confidential = TRUE) - var/datum/admin_help/AH = admin_ticket_log(src, "Reply PM from-[key_name(src, TRUE, TRUE)] to External: [keywordparsedmsg]") + var/datum/admin_help/new_admin_help = admin_ticket_log(src, "Reply PM from-[key_name(src, TRUE, TRUE)] to External: [keywordparsedmsg]", player_message = "Reply PM from-[key_name(src, TRUE, FALSE)] to External: [msg]") externalreplyamount-- - send2adminchat("[AH ? "#[AH.id] " : ""]Reply: [ckey]", rawmsg) + send2adminchat("[new_admin_help ? "#[new_admin_help.id] " : ""]Reply: [ckey]", rawmsg) else var/badmin = FALSE //Lets figure out if an admin is getting bwoinked. if(holder && recipient.holder && !current_ticket) //Both are admins, and this is not a reply to our own ticket. @@ -234,14 +234,16 @@ html = span_notice("Admin PM to-[key_name(recipient, src, 1)]: [keywordparsedmsg]"), confidential = TRUE) //omg this is dumb, just fill in both their tickets - var/interaction_message = "PM from-[key_name(src, recipient, 1)] to-[key_name(recipient, src, 1)]: [keywordparsedmsg]" - admin_ticket_log(src, interaction_message, log_in_blackbox = FALSE) + var/interaction_message = "PM from-[key_name(src, recipient, TRUE)] to-[key_name(recipient, src, TRUE)]: [keywordparsedmsg]" + var/player_interaction_message = "PM from-[key_name(src, recipient, FALSE)] to-[key_name(recipient, src, FALSE)]: [msg]" + admin_ticket_log(src, interaction_message, log_in_blackbox = FALSE, player_message = player_interaction_message) if(recipient != src) //reeee - admin_ticket_log(recipient, interaction_message, log_in_blackbox = FALSE) + admin_ticket_log(recipient, interaction_message, log_in_blackbox = FALSE, player_message = player_interaction_message) SSblackbox.LogAhelp(current_ticket.id, "Reply", msg, recipient.ckey, src.ckey) else //recipient is an admin but sender is not - var/replymsg = "Reply PM from-[key_name(src, recipient, 1)]: [keywordparsedmsg]" - admin_ticket_log(src, "[replymsg]", log_in_blackbox = FALSE) + var/replymsg = "Reply PM from-[key_name(src, recipient, TRUE)]: [keywordparsedmsg]" + var/player_replymsg = "Reply PM from-[key_name(src, recipient, FALSE)]: [msg]" + admin_ticket_log(src, "[replymsg]", log_in_blackbox = FALSE, player_message = player_replymsg) to_chat(recipient, type = MESSAGE_TYPE_ADMINPM, html = span_danger("[replymsg]"), @@ -280,7 +282,7 @@ html = span_notice("Admin PM to-[key_name(recipient, src, 1)]: [msg]"), confidential = TRUE) - admin_ticket_log(recipient, "PM From [key_name_admin(src)]: [keywordparsedmsg]", log_in_blackbox = FALSE) + admin_ticket_log(recipient, "PM From [key_name_admin(src)]: [keywordparsedmsg]", log_in_blackbox = FALSE, player_message = "PM From [key_name_admin(src, include_name = FALSE)]: [msg]") if(!already_logged) //Reply to an existing ticket SSblackbox.LogAhelp(recipient.current_ticket.id, "Reply", msg, recipient.ckey, src.ckey) diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index 982648b6f13..fad493d9ee4 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -100,6 +100,9 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( if(href_list["priv_msg"]) cmd_admin_pm(href_list["priv_msg"],null) return + if (href_list["player_ticket_panel"]) + view_latest_ticket() + return // TGUIless adminhelp if(href_list["tguiless_adminhelp"]) no_tgui_adminhelp(input(src, "Enter your ahelp", "Ahelp") as null|message)