Implemented multi-select functionality and basic context-menu for session table.

This commit is contained in:
Jakob Friedl
2025-09-09 22:55:43 +02:00
parent 2320b705d3
commit 5f131ae916
3 changed files with 136 additions and 56 deletions

View File

@@ -1,13 +1,13 @@
import times
import imguin/[cimgui, glfw_opengl, simple]
import ../utils/appImGui
import ../../common/[types]
import ../../common/[types, utils]
type
SessionsTableComponent = ref object of RootObj
title: string
agents: seq[Agent]
selection: ptr ImGuiSelectionBasicStorage
let exampleAgents: seq[Agent] = @[
Agent(
@@ -43,6 +43,40 @@ let exampleAgents: seq[Agent] = @[
firstCheckin: now() - initDuration(hours = 1, minutes = 30),
latestCheckin: now() - initDuration(minutes = 5),
sessionKey: [byte 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
),
Agent(
agentId: "C9D8E7F6",
listenerId: "L2468135",
username: "charlie",
hostname: "SERVER-03",
domain: "IT",
ip: "172.16.0.20",
os: "Windows Server 2019",
process: "powershell.exe",
pid: 7890,
elevated: true,
sleep: 30,
tasks: @[],
firstCheckin: now() - initDuration(hours = 3, minutes = 15),
latestCheckin: now() - initDuration(minutes = 10),
sessionKey: [byte 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
),
Agent(
agentId: "G1H2I3J4",
listenerId: "L1357924",
username: "diana",
hostname: "WORKSTATION-04",
domain: "HR",
ip: "192.168.2.15",
os: "Windows 10",
process: "chrome.exe",
pid: 3210,
elevated: false,
sleep: 90,
tasks: @[],
firstCheckin: now() - initDuration(hours = 4),
latestCheckin: now() - initDuration(minutes = 2),
sessionKey: [byte 5, 4, 3, 2, 1, 0, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6]
)
]
@@ -50,6 +84,7 @@ proc SessionsTable*(title: string): SessionsTableComponent =
result = new SessionsTableComponent
result.title = title
result.agents = exampleAgents
result.selection = ImGuiSelectionBasicStorage_ImGuiSelectionBasicStorage()
proc draw*(component: SessionsTableComponent, showComponent: ptr bool) =
igSetNextWindowSize(vec2(800, 600), ImGuiCond_Once.int32)
@@ -62,13 +97,12 @@ proc draw*(component: SessionsTableComponent, showComponent: ptr bool) =
ImGuiTableFlags_Reorderable.int32 or
ImGuiTableFlags_Hideable.int32 or
ImGuiTableFlags_HighlightHoveredColumn.int32 or
ImGuiTableFlags_ContextMenuInBody.int32 or
ImGuiTableFlags_RowBg.int32 or
ImGuiTableFlags_BordersV.int32 or
ImGuiTableFlags_BordersH.int32 or
ImGuiTableFlags_ScrollY.int32 or
ImGuiTableFlags_ScrollX.int32 or
ImGuiTableFlags_NoBordersInBodyUntilResize.int32 or
ImGuiTableFlags_NoBordersInBodyUntilResize.int32 or
ImGui_TableFlags_SizingStretchProp.int32
)
@@ -86,12 +120,20 @@ proc draw*(component: SessionsTableComponent, showComponent: ptr bool) =
igTableSetupScrollFreeze(0, 1)
igTableHeadersRow()
var multiSelectIO = igBeginMultiSelect(ImGuiMultiSelectFlags_ClearOnEscape.int32 or ImGuiMultiSelectFlags_BoxSelect1d.int32, component.selection[].Size, int32(component.agents.len()))
ImGuiSelectionBasicStorage_ApplyRequests(component.selection, multiSelectIO)
for row in 0..< component.agents.len():
igTableNextRow(ImGuiTableRowFlags_None.int32, 0.0f)
let agent = component.agents[row]
if igTableSetColumnIndex(0):
igText(agent.agentId)
if igTableSetColumnIndex(0):
# Enable multi-select functionality
igSetNextItemSelectionUserData(row)
var isSelected = ImGuiSelectionBasicStorage_Contains(component.selection, cast[ImGuiID](row))
discard igSelectable_Bool(agent.agentId, isSelected, ImGuiSelectableFlags_SpanAllColumns.int32, vec2(0.0f, 0.0f))
if igTableSetColumnIndex(1):
igText(agent.ip)
if igTableSetColumnIndex(2):
@@ -107,6 +149,23 @@ proc draw*(component: SessionsTableComponent, showComponent: ptr bool) =
if igTableSetColumnIndex(7):
igText(agent.latestCheckin.format("yyyy-MM-dd HH:mm:ss"))
# Handle right-click context menu
# Right-clicking the table header to hide/show columns or reset the layout is only possible when no sessions are selected
if component.selection[].Size > 0 and igBeginPopupContextWindow("TableContextMenu", ImGui_PopupFlags_MouseButtonRight.int32):
if igMenuItem("Interact", "ENTER", false, true):
igCloseCurrentPopup()
if igMenuItem("Remove", "DELETE", false, true):
igCloseCurrentPopup()
igEndPopup()
multiSelectIO = igEndMultiSelect()
ImGuiSelectionBasicStorage_ApplyRequests(component.selection, multiSelectIO)
igEndTable()