Implemented right-click context menu on session table to create console windows for interacting with the agent.
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
[Window][Dockspace]
|
[Window][Dockspace]
|
||||||
Pos=0,0
|
Pos=0,0
|
||||||
Size=2548,1359
|
Size=2868,1695
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
|
|
||||||
[Window][Debug##Default]
|
[Window][Debug##Default]
|
||||||
@@ -9,28 +9,28 @@ Size=449,261
|
|||||||
Collapsed=0
|
Collapsed=0
|
||||||
|
|
||||||
[Window][Dear ImGui Demo]
|
[Window][Dear ImGui Demo]
|
||||||
Pos=1852,43
|
Pos=1884,43
|
||||||
Size=686,653
|
Size=974,624
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000007,0
|
DockId=0x00000006,1
|
||||||
|
|
||||||
[Window][Agents [Table View]]
|
[Window][Agents [Table View]]
|
||||||
Pos=10,43
|
Pos=10,43
|
||||||
Size=1187,946
|
Size=1187,946
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000006,0
|
DockId=0x00000005,0
|
||||||
|
|
||||||
[Window][Agents [Graph View]]
|
[Window][Agents [Graph View]]
|
||||||
Pos=10,43
|
Pos=10,43
|
||||||
Size=1888,473
|
Size=1888,473
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000006,1
|
DockId=0x00000005,1
|
||||||
|
|
||||||
[Window][Eventlog]
|
[Window][Eventlog]
|
||||||
Pos=10,698
|
Pos=1884,43
|
||||||
Size=2528,651
|
Size=974,624
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000004,0
|
DockId=0x00000006,0
|
||||||
|
|
||||||
[Window][Example: Assets Browser]
|
[Window][Example: Assets Browser]
|
||||||
Pos=60,60
|
Pos=60,60
|
||||||
@@ -51,7 +51,7 @@ Collapsed=0
|
|||||||
Pos=10,698
|
Pos=10,698
|
||||||
Size=2528,651
|
Size=2528,651
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000004,1
|
DockId=0x00000005,1
|
||||||
|
|
||||||
[Window][Dear ImGui Metrics/Debugger]
|
[Window][Dear ImGui Metrics/Debugger]
|
||||||
Pos=60,60
|
Pos=60,60
|
||||||
@@ -60,9 +60,9 @@ Collapsed=0
|
|||||||
|
|
||||||
[Window][Sessions [Table View]]
|
[Window][Sessions [Table View]]
|
||||||
Pos=10,43
|
Pos=10,43
|
||||||
Size=1840,653
|
Size=1872,624
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000006,0
|
DockId=0x00000005,0
|
||||||
|
|
||||||
[Window][Dear ImGui Demo/ResizableChild_478B81A3]
|
[Window][Dear ImGui Demo/ResizableChild_478B81A3]
|
||||||
IsChild=1
|
IsChild=1
|
||||||
@@ -98,6 +98,60 @@ DockId=0x00000002,0
|
|||||||
IsChild=1
|
IsChild=1
|
||||||
Size=614,540
|
Size=614,540
|
||||||
|
|
||||||
|
[Window][Listeners]
|
||||||
|
Pos=10,765
|
||||||
|
Size=2848,920
|
||||||
|
Collapsed=0
|
||||||
|
DockId=0x00000004,0
|
||||||
|
|
||||||
|
[Window][G1H2I3J4]
|
||||||
|
Pos=10,866
|
||||||
|
Size=2848,819
|
||||||
|
Collapsed=0
|
||||||
|
DockId=0x00000008,1
|
||||||
|
|
||||||
|
[Window][C9D8E7F6]
|
||||||
|
Pos=10,866
|
||||||
|
Size=2848,819
|
||||||
|
Collapsed=0
|
||||||
|
DockId=0x00000008,2
|
||||||
|
|
||||||
|
[Window][FACEDEAD]
|
||||||
|
Pos=10,866
|
||||||
|
Size=2848,819
|
||||||
|
Collapsed=0
|
||||||
|
DockId=0x00000008,3
|
||||||
|
|
||||||
|
[Window][["C9D8E7F6"] charlie@SERVER-03]
|
||||||
|
Pos=10,866
|
||||||
|
Size=2848,819
|
||||||
|
Collapsed=0
|
||||||
|
DockId=0x00000008,1
|
||||||
|
|
||||||
|
[Window][[G1H2I3J4] diana@WORKSTATION-04]
|
||||||
|
Pos=10,669
|
||||||
|
Size=2848,1016
|
||||||
|
Collapsed=0
|
||||||
|
DockId=0x00000008,1
|
||||||
|
|
||||||
|
[Window][[FACEDEAD] bob@LAPTOP-02]
|
||||||
|
Pos=10,669
|
||||||
|
Size=2848,1016
|
||||||
|
Collapsed=0
|
||||||
|
DockId=0x00000008,0
|
||||||
|
|
||||||
|
[Window][[C9D8E7F6] charlie@SERVER-03]
|
||||||
|
Pos=10,669
|
||||||
|
Size=2848,1016
|
||||||
|
Collapsed=0
|
||||||
|
DockId=0x00000008,2
|
||||||
|
|
||||||
|
[Window][[DEADBEEF] alice@DESKTOP-01]
|
||||||
|
Pos=10,669
|
||||||
|
Size=2848,1016
|
||||||
|
Collapsed=0
|
||||||
|
DockId=0x00000008,1
|
||||||
|
|
||||||
[Table][0xB6880529,2]
|
[Table][0xB6880529,2]
|
||||||
RefScale=27
|
RefScale=27
|
||||||
Column 0 Sort=0v
|
Column 0 Sort=0v
|
||||||
@@ -112,14 +166,14 @@ Column 4 Weight=1.0000
|
|||||||
Column 5 Width=-1
|
Column 5 Width=-1
|
||||||
|
|
||||||
[Table][0x32886A44,8]
|
[Table][0x32886A44,8]
|
||||||
Column 0 Weight=0.7126
|
Column 0 Weight=0.6558
|
||||||
Column 1 Weight=1.0615
|
Column 1 Weight=0.9747
|
||||||
Column 2 Weight=0.7126
|
Column 2 Weight=0.6558
|
||||||
Column 3 Weight=1.2397
|
Column 3 Weight=0.8804
|
||||||
Column 4 Weight=1.6776
|
Column 4 Weight=1.8057
|
||||||
Column 5 Weight=1.2397
|
Column 5 Weight=1.1454
|
||||||
Column 6 Weight=0.3563
|
Column 6 Weight=0.3324
|
||||||
Column 7 Weight=1.5466
|
Column 7 Weight=1.5497
|
||||||
|
|
||||||
[Table][0x51D6F5EA,3]
|
[Table][0x51D6F5EA,3]
|
||||||
Column 0 Weight=1.0000
|
Column 0 Weight=1.0000
|
||||||
@@ -264,11 +318,13 @@ Column 1 Width=119
|
|||||||
Column 2 Width=119
|
Column 2 Width=119
|
||||||
|
|
||||||
[Docking][Data]
|
[Docking][Data]
|
||||||
DockSpace ID=0x85940918 Window=0x260A4489 Pos=10,43 Size=2528,1306 Split=Y
|
DockSpace ID=0x85940918 Window=0x260A4489 Pos=10,43 Size=2848,1642 Split=Y
|
||||||
DockNode ID=0x00000001 Parent=0x85940918 SizeRef=1453,473 Split=Y Selected=0x61E02D75
|
DockNode ID=0x00000007 Parent=0x85940918 SizeRef=2848,624 Split=Y
|
||||||
DockNode ID=0x00000003 Parent=0x00000001 SizeRef=2528,653 Split=X Selected=0x61E02D75
|
DockNode ID=0x00000003 Parent=0x00000007 SizeRef=2848,720 Split=Y
|
||||||
DockNode ID=0x00000006 Parent=0x00000003 SizeRef=1840,653 CentralNode=1 Selected=0x61E02D75
|
DockNode ID=0x00000001 Parent=0x00000003 SizeRef=1453,473 Split=X Selected=0x61E02D75
|
||||||
DockNode ID=0x00000007 Parent=0x00000003 SizeRef=686,653 Selected=0x5E5F7166
|
DockNode ID=0x00000005 Parent=0x00000001 SizeRef=1872,674 CentralNode=1 Selected=0x61E02D75
|
||||||
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=2528,651 Selected=0x0FA43D88
|
DockNode ID=0x00000006 Parent=0x00000001 SizeRef=974,674 Selected=0x5E5F7166
|
||||||
DockNode ID=0x00000002 Parent=0x85940918 SizeRef=1453,471 Selected=0x6D7E7D39
|
DockNode ID=0x00000002 Parent=0x00000003 SizeRef=1453,471 Selected=0x6D7E7D39
|
||||||
|
DockNode ID=0x00000004 Parent=0x00000007 SizeRef=2848,920 Selected=0x6BE22050
|
||||||
|
DockNode ID=0x00000008 Parent=0x85940918 SizeRef=2848,1016 Selected=0xD3469193
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import tables
|
import tables
|
||||||
import ./utils/appImGui
|
import ./utils/appImGui
|
||||||
import ./views/[dockspace, sessions, listeners, eventlog]
|
import ./views/[dockspace, sessions, listeners, eventlog, console]
|
||||||
|
|
||||||
proc main() =
|
proc main() =
|
||||||
var app = createApp(1024, 800, imnodes = true, title = "Conquest", docking = true)
|
var app = createApp(1024, 800, imnodes = true, title = "Conquest", docking = true)
|
||||||
@@ -13,6 +13,7 @@ proc main() =
|
|||||||
showSessionsGraph = false
|
showSessionsGraph = false
|
||||||
showListeners = false
|
showListeners = false
|
||||||
showEventlog = true
|
showEventlog = true
|
||||||
|
consoles: Table[string, ConsoleComponent]
|
||||||
|
|
||||||
views["Sessions [Table View]"] = addr showSessionsTable
|
views["Sessions [Table View]"] = addr showSessionsTable
|
||||||
views["Sessions [Graph View]"] = addr showSessionsGraph
|
views["Sessions [Graph View]"] = addr showSessionsGraph
|
||||||
@@ -22,12 +23,10 @@ proc main() =
|
|||||||
# Create components
|
# Create components
|
||||||
var
|
var
|
||||||
dockspace = Dockspace()
|
dockspace = Dockspace()
|
||||||
sessionsTable = SessionsTable("Sessions [Table View]")
|
sessionsTable = SessionsTable("Sessions [Table View]", addr consoles)
|
||||||
sessionsGraph = SessionsTable("Sessions [Graph View]")
|
|
||||||
listenersTable = ListenersTable("Listeners")
|
listenersTable = ListenersTable("Listeners")
|
||||||
eventlog = Eventlog("Eventlog")
|
eventlog = Eventlog("Eventlog")
|
||||||
|
|
||||||
|
|
||||||
let io = igGetIO()
|
let io = igGetIO()
|
||||||
|
|
||||||
# main loop
|
# main loop
|
||||||
@@ -45,6 +44,17 @@ proc main() =
|
|||||||
if showListeners: listenersTable.draw(addr showListeners)
|
if showListeners: listenersTable.draw(addr showListeners)
|
||||||
if showEventlog: eventlog.draw(addr showEventlog)
|
if showEventlog: eventlog.draw(addr showEventlog)
|
||||||
|
|
||||||
|
# Show console windows
|
||||||
|
var newConsoleTable: Table[string, ConsoleComponent]
|
||||||
|
for agentId, console in consoles.mpairs():
|
||||||
|
if console.showConsole:
|
||||||
|
console.draw()
|
||||||
|
newConsoleTable[agentId] = console
|
||||||
|
|
||||||
|
# Update the consoles table with only those sessions that have not been closed yet
|
||||||
|
# This is done to ensure that closed console windows can be opened again
|
||||||
|
consoles = newConsoleTable
|
||||||
|
|
||||||
igShowDemoWindow(nil)
|
igShowDemoWindow(nil)
|
||||||
|
|
||||||
# render
|
# render
|
||||||
|
|||||||
25
src/client/views/console.nim
Normal file
25
src/client/views/console.nim
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import strformat
|
||||||
|
import imguin/[cimgui, glfw_opengl, simple]
|
||||||
|
import ../utils/appImGui
|
||||||
|
import ../../common/[types]
|
||||||
|
|
||||||
|
type
|
||||||
|
ConsoleComponent* = ref object of RootObj
|
||||||
|
agent: Agent
|
||||||
|
showConsole*: bool
|
||||||
|
|
||||||
|
proc Console*(agent: Agent): ConsoleComponent =
|
||||||
|
result = new ConsoleComponent
|
||||||
|
result.agent = agent
|
||||||
|
result.showConsole = true
|
||||||
|
|
||||||
|
proc draw*(component: ConsoleComponent) =
|
||||||
|
igSetNextWindowSize(vec2(800, 600), ImGuiCond_Once.int32)
|
||||||
|
|
||||||
|
# var showComponent = component.showConsole
|
||||||
|
igBegin(fmt"[{component.agent.agentId}] {component.agent.username}@{component.agent.hostname}", addr component.showConsole, 0)
|
||||||
|
defer: igEnd()
|
||||||
|
|
||||||
|
igText(component.agent.agentId)
|
||||||
|
|
||||||
|
# component.showConsole = showComponent
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
import times
|
import times, tables, strformat
|
||||||
import imguin/[cimgui, glfw_opengl, simple]
|
import imguin/[cimgui, glfw_opengl, simple]
|
||||||
|
|
||||||
|
import ./console
|
||||||
import ../utils/appImGui
|
import ../utils/appImGui
|
||||||
import ../../common/[types, utils]
|
import ../../common/[types, utils]
|
||||||
|
|
||||||
@@ -8,6 +10,7 @@ type
|
|||||||
title: string
|
title: string
|
||||||
agents: seq[Agent]
|
agents: seq[Agent]
|
||||||
selection: ptr ImGuiSelectionBasicStorage
|
selection: ptr ImGuiSelectionBasicStorage
|
||||||
|
consoles: ptr Table[string, ConsoleComponent]
|
||||||
|
|
||||||
let exampleAgents: seq[Agent] = @[
|
let exampleAgents: seq[Agent] = @[
|
||||||
Agent(
|
Agent(
|
||||||
@@ -80,11 +83,28 @@ let exampleAgents: seq[Agent] = @[
|
|||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
proc SessionsTable*(title: string): SessionsTableComponent =
|
proc SessionsTable*(title: string, consoles: ptr Table[string, ConsoleComponent]): SessionsTableComponent =
|
||||||
result = new SessionsTableComponent
|
result = new SessionsTableComponent
|
||||||
result.title = title
|
result.title = title
|
||||||
result.agents = exampleAgents
|
result.agents = exampleAgents
|
||||||
result.selection = ImGuiSelectionBasicStorage_ImGuiSelectionBasicStorage()
|
result.selection = ImGuiSelectionBasicStorage_ImGuiSelectionBasicStorage()
|
||||||
|
result.consoles = consoles
|
||||||
|
|
||||||
|
proc interact(component: SessionsTableComponent) =
|
||||||
|
# Open a new console for each selected agent session
|
||||||
|
var it: pointer = nil
|
||||||
|
var row: ImGuiID
|
||||||
|
while ImGuiSelectionBasicStorage_GetNextSelectedItem(component.selection, addr it, addr row):
|
||||||
|
let agent = component.agents[cast[int](row)]
|
||||||
|
|
||||||
|
# Create a new console window
|
||||||
|
if not component.consoles[].hasKey(agent.agentId):
|
||||||
|
component.consoles[][agent.agentId] = Console(agent)
|
||||||
|
|
||||||
|
# Focus the existing console window
|
||||||
|
else:
|
||||||
|
igSetWindowFocus_Str(fmt"[{agent.agentId}] {agent.username}@{agent.hostname}")
|
||||||
|
|
||||||
|
|
||||||
proc draw*(component: SessionsTableComponent, showComponent: ptr bool) =
|
proc draw*(component: SessionsTableComponent, showComponent: ptr bool) =
|
||||||
igSetNextWindowSize(vec2(800, 600), ImGuiCond_Once.int32)
|
igSetNextWindowSize(vec2(800, 600), ImGuiCond_Once.int32)
|
||||||
@@ -134,6 +154,11 @@ proc draw*(component: SessionsTableComponent, showComponent: ptr bool) =
|
|||||||
igSetNextItemSelectionUserData(row)
|
igSetNextItemSelectionUserData(row)
|
||||||
var isSelected = ImGuiSelectionBasicStorage_Contains(component.selection, cast[ImGuiID](row))
|
var isSelected = ImGuiSelectionBasicStorage_Contains(component.selection, cast[ImGuiID](row))
|
||||||
discard igSelectable_Bool(agent.agentId, isSelected, ImGuiSelectableFlags_SpanAllColumns.int32, vec2(0.0f, 0.0f))
|
discard igSelectable_Bool(agent.agentId, isSelected, ImGuiSelectableFlags_SpanAllColumns.int32, vec2(0.0f, 0.0f))
|
||||||
|
|
||||||
|
# Interact with session on double-click
|
||||||
|
if igIsMouseDoubleClicked_Nil(ImGui_MouseButton_Left.int32):
|
||||||
|
component.interact()
|
||||||
|
|
||||||
if igTableSetColumnIndex(1):
|
if igTableSetColumnIndex(1):
|
||||||
igText(agent.ip)
|
igText(agent.ip)
|
||||||
if igTableSetColumnIndex(2):
|
if igTableSetColumnIndex(2):
|
||||||
@@ -153,15 +178,23 @@ proc draw*(component: SessionsTableComponent, showComponent: ptr bool) =
|
|||||||
# Right-clicking the table header to hide/show columns or reset the layout is only possible when no sessions are selected
|
# 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 component.selection[].Size > 0 and igBeginPopupContextWindow("TableContextMenu", ImGui_PopupFlags_MouseButtonRight.int32):
|
||||||
|
|
||||||
if igMenuItem("Interact", "ENTER", false, true):
|
if igMenuItem("Interact", nil, false, true):
|
||||||
|
component.interact()
|
||||||
igCloseCurrentPopup()
|
igCloseCurrentPopup()
|
||||||
|
|
||||||
if igMenuItem("Remove", "DELETE", false, true):
|
if igMenuItem("Remove", nil, false, true):
|
||||||
|
# Update agents table with only non-selected ones
|
||||||
|
var newAgents: seq[Agent] = @[]
|
||||||
|
for i in 0 ..< component.agents.len():
|
||||||
|
if not ImGuiSelectionBasicStorage_Contains(component.selection, cast[ImGuiID](i)):
|
||||||
|
newAgents.add(component.agents[i])
|
||||||
|
|
||||||
|
component.agents = newAgents
|
||||||
|
ImGuiSelectionBasicStorage_Clear(component.selection)
|
||||||
igCloseCurrentPopup()
|
igCloseCurrentPopup()
|
||||||
|
|
||||||
igEndPopup()
|
igEndPopup()
|
||||||
|
|
||||||
|
|
||||||
multiSelectIO = igEndMultiSelect()
|
multiSelectIO = igEndMultiSelect()
|
||||||
ImGuiSelectionBasicStorage_ApplyRequests(component.selection, multiSelectIO)
|
ImGuiSelectionBasicStorage_ApplyRequests(component.selection, multiSelectIO)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user