diff --git a/code/modules/admin/admin_tools.dm b/code/modules/admin/admin_tools.dm index 6284e6bd52..fbbb75a3d2 100644 --- a/code/modules/admin/admin_tools.dm +++ b/code/modules/admin/admin_tools.dm @@ -2,39 +2,9 @@ ADMIN_VERB_ONLY_CONTEXT_MENU(cmd_admin_check_player_logs, R_ADMIN|R_MOD, "Check user.show_cmd_admin_check_player_logs(player.logging, player.name, player.ckey, player.mind?.special_role) //Views specific attack logs belonging to one player. -/client/proc/show_cmd_admin_check_player_logs(list/mob_data, target_name, target_ckey, target_special) - if(CONFIG_GET(flag/database_logging)) - var/datum/db_query/query = SSdbcore.NewQuery("SELECT mid,time,ckey,mob,area,color,type,message from erro_dialog WHERE ckey = :t_ckey", list("t_ckey" = ckey)) - if(!query.Execute()) - to_chat(src, span_admin("Database query error")) - qdel(query) - return - - var/list/data = list() - while(query.NextRow()) - var/list/timestamped_message = list( - "event_id" = query.item[1], - "time" = query.item[2], - "ckey" = query.item[3], - "name" = query.item[4], - "loc" = query.item[5], - "color" = query.item[6], - "message" = query.item[8] - ) - var/entry_type = query.item[7] - if(!islist(data[entry_type])) - data[entry_type] = list() - UNTYPED_LIST_ADD(data[entry_type], timestamped_message) - qdel(query) - if(!length(data)) - to_chat(src, span_admin("No data found.")) - return - admin_log_view_target(data, target_name, target_ckey, target_special) - return - if(!length(mob_data)) - to_chat(src, span_admin("No data found.")) - return - admin_log_view_target(mob_data, target_name, target_ckey, target_special) +/client/proc/show_cmd_admin_check_player_logs(list/mob_data, target_name, target_ckey, target_special, is_client) + var/datum/player_log_viwer/log_view = new(mob_data, target_name, target_ckey, target_special, is_client) + log_view.tgui_interact(mob) ADMIN_VERB(persistent_client_logs, R_ADMIN|R_MOD, "Check Player Logs", "Displays the client logs of the selected ckey.", ADMIN_CATEGORY_LOGS) var/mob/living/selected_key = tgui_input_list(user, "Select a ckey to check their logs", "Ckey", GLOB.persistent_clients_by_ckey) @@ -43,28 +13,31 @@ ADMIN_VERB(persistent_client_logs, R_ADMIN|R_MOD, "Check Player Logs", "Displays var/datum/persistent_client/selected = GLOB.persistent_clients_by_ckey[selected_key] - user.show_cmd_admin_check_player_logs(selected.logging, selected.mob?.name, selected_key, selected.mob?.mind?.special_role) - -/client/proc/admin_log_view_target(list/log_data, name, ckey, special, use_db) - var/datum/player_log_viwer/log_view = new(log_data, name, ckey, special) - log_view.tgui_interact(mob) + user.show_cmd_admin_check_player_logs(selected.logging, selected.mob?.name, selected_key, selected.mob?.mind?.special_role, TRUE) /datum/player_log_viwer var/list/log_data var/target_name var/target_ckey var/special_role + var/last_refresh + var/client_view /datum/player_log_viwer/tgui_close(mob/user) . = ..() log_data = null -/datum/player_log_viwer/New(list/data, name, ckey, special) +/datum/player_log_viwer/New(list/data, name, ckey, special, is_client) . = ..() log_data = data target_name = name target_ckey = ckey special_role = special + last_refresh = world.time + client_view = is_client + if(!islist(log_data)) + log_data = list() + refresh_data() /datum/player_log_viwer/tgui_interact(mob/user, datum/tgui/ui) ui = SStgui.try_update_ui(user, src, ui) @@ -80,5 +53,72 @@ ADMIN_VERB(persistent_client_logs, R_ADMIN|R_MOD, "Check Player Logs", "Displays "entries" = log_data, "name" = target_name, "ckey" = target_ckey, - "special" = special_role + "special" = special_role, + "view_client" = client_view ) + +/datum/player_log_viwer/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state) + return list( + "on_cooldown" = refresh_cooldown(), + "all_clients" = GLOB.persistent_clients_by_ckey, + ) + +/datum/player_log_viwer/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state) + . = ..() + if(.) + return + + switch(action) + if("refresh") + if(refresh_cooldown()) + return FALSE + refresh_data() + last_refresh = world.time + update_tgui_static_data(ui.user) + return TRUE + if("select_client") + if(refresh_cooldown()) + return FALSE + var/new_ckey = params["ckey"] + if(!(new_ckey in GLOB.persistent_clients_by_ckey)) + return FALSE + target_ckey = new_ckey + var/datum/persistent_client/selected = GLOB.persistent_clients_by_ckey[new_ckey] + log_data = selected.logging + target_name = selected.mob?.name + special_role = selected.mob?.mind?.special_role + client_view = TRUE + refresh_data() + last_refresh = world.time + update_tgui_static_data(ui.user) + return TRUE + +/datum/player_log_viwer/proc/refresh_cooldown() + return ((world.time - last_refresh) < 5 SECONDS) + +/datum/player_log_viwer/proc/refresh_data() + if(!CONFIG_GET(flag/database_logging)) + return + var/datum/db_query/query = SSdbcore.NewQuery("SELECT mid,time,ckey,mob,area,color,type,message from erro_dialog WHERE ckey = :t_ckey", list("t_ckey" = target_ckey)) + if(!query.Execute()) + to_chat(src, span_admin("Database query error")) + qdel(query) + return + + log_data.Cut() + while(query.NextRow()) + var/list/timestamped_message = list( + "event_id" = query.item[1], + "time" = query.item[2], + "ckey" = query.item[3], + "name" = query.item[4], + "loc" = query.item[5], + "color" = query.item[6], + "message" = query.item[8] + ) + var/entry_type = query.item[7] + if(!islist(log_data[entry_type])) + log_data[entry_type] = list() + UNTYPED_LIST_ADD(log_data[entry_type], timestamped_message) + client_view = TRUE + qdel(query) diff --git a/tgui/packages/tgui/interfaces/PlayerLogViewer/index.tsx b/tgui/packages/tgui/interfaces/PlayerLogViewer/index.tsx index d5446ab021..7912d88106 100644 --- a/tgui/packages/tgui/interfaces/PlayerLogViewer/index.tsx +++ b/tgui/packages/tgui/interfaces/PlayerLogViewer/index.tsx @@ -1,12 +1,21 @@ import { useState } from 'react'; import { useBackend } from 'tgui/backend'; import { Window } from 'tgui/layouts'; -import { Box, Button, Input, Section, Stack, Tabs } from 'tgui-core/components'; +import { + Box, + Button, + Dropdown, + Input, + LabeledList, + Section, + Stack, + Tabs, +} from 'tgui-core/components'; import { displayTime, stripHtml } from './function'; import type { Data, ExtendedLogEntry } from './types'; export const PlayerLogViewer = (props) => { - const { data } = useBackend(); + const { data, act } = useBackend(); const [activeTab, setActiveTab] = useState(''); const [search, setSearch] = useState(''); @@ -16,7 +25,15 @@ export const PlayerLogViewer = (props) => { setSearchRegex(false); } - const { entries, name, ckey, special } = data; + const { + entries, + name, + ckey, + special, + on_cooldown, + all_clients, + view_client, + } = data; const allEntries = Object.entries(entries) .flatMap(([category, logs]) => @@ -42,23 +59,54 @@ export const PlayerLogViewer = (props) => { -
- - - {`Viewing logs of `} - - {name} - - {`, played by `} - - {ckey ?? ''} - +
+ + Select a ckey to view client logs:{' '} + + + + act('select_client', { ckey: value }) + } + /> + + + } + > + + + + + + {name} + + + + + {ckey ?? ''} + + + - - {`Characrer special role: `} - - {special ? special : ''} - + + + + + {view_client ? 'Client' : 'Mob'} Logs + + + + + {special ? special : ''} + + +
@@ -83,6 +131,13 @@ export const PlayerLogViewer = (props) => { title={`Active Log: ${activeTab}`} buttons={ + +