Added OTP Activity Review WIP
This commit is contained in:
+41
-15
@@ -1,11 +1,13 @@
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
from typing import Optional
|
||||
|
||||
import dotenv
|
||||
from dotenv import set_key
|
||||
from textual.app import App, ComposeResult
|
||||
from textual.containers import Vertical
|
||||
from textual.message import Message
|
||||
from textual.reactive import reactive
|
||||
from textual.screen import Screen
|
||||
from textual.widgets import (
|
||||
@@ -18,25 +20,26 @@ from textual.widgets import (
|
||||
Tabs,
|
||||
)
|
||||
|
||||
from flows.otp import otp_activities_by_agent, otp_revoke
|
||||
from flows.otp import otp_revoke
|
||||
from flows.prepPolicy import menu_policy_enforce
|
||||
from flows.quietAgent import findQuietAgents
|
||||
from models.agent import Agent
|
||||
from models.policy import Policy
|
||||
from screens.moveagentworkflowscreen import MoveAgentWorkflowScreen
|
||||
from screens.otpactivityscreen import OTPActivitiesScreen
|
||||
from screens.otpworkflowscreen import OTPWorkflowScreen
|
||||
from services.API import AirlockAPIWrapper
|
||||
from services.policyhandler import confirmUpdateAfromE
|
||||
from themes.amber_terminal_theme import get_amber_terminal_theme
|
||||
from themes.retro_terminal_theme import get_retro_terminal_theme
|
||||
from utils.configmanager import load_env
|
||||
from utils.setup import get_base_directory, load_user_config
|
||||
from utils.utils import open_directory
|
||||
from widgets.agentmoveoperations import AgentMoveOperations
|
||||
from widgets.amber_terminal_theme import get_amber_terminal_theme
|
||||
from widgets.multiagentselector import MultiAgentSelector
|
||||
from widgets.OTP_generate import OTPGenerator
|
||||
from widgets.policytreewidget import PolicyTreeWidget
|
||||
from widgets.resultsdisplay import ResultsDisplay
|
||||
from widgets.retro_terminal_theme import get_retro_terminal_theme
|
||||
from widgets.themeselector import ThemeSelector
|
||||
|
||||
dotenv.load_dotenv()
|
||||
@@ -102,6 +105,7 @@ def _persist_user_theme(theme_name: str) -> None:
|
||||
# 1) SCREEN
|
||||
# ---------------------------------------------------------------------------
|
||||
class MainMenuScreen(Screen):
|
||||
api: AirlockAPIWrapper
|
||||
current_tab = reactive("")
|
||||
|
||||
BUTTON_DEFS = {
|
||||
@@ -120,9 +124,8 @@ class MainMenuScreen(Screen):
|
||||
],
|
||||
}
|
||||
|
||||
def __init__(self, api: AirlockAPIWrapper) -> None:
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
self.api = api
|
||||
self.extras = load_env("EXTRAS")
|
||||
wd = load_env("WORKING_DIR") or os.getcwd()
|
||||
if not os.path.isdir(wd):
|
||||
@@ -156,6 +159,7 @@ class MainMenuScreen(Screen):
|
||||
yield Footer()
|
||||
|
||||
def on_mount(self) -> None:
|
||||
api = self.app.api
|
||||
self.switch_tab("agent_actions")
|
||||
|
||||
# focus helpers
|
||||
@@ -321,34 +325,55 @@ class MainMenuScreen(Screen):
|
||||
self.app.push_screen(MoveAgentWorkflowScreen(self.app.devices))
|
||||
event.stop()
|
||||
return # Don't exit the app
|
||||
|
||||
case "otp_generate_button":
|
||||
# NEW: Push OTP workflow screen instead of legacy function
|
||||
self.app.push_screen(OTPWorkflowScreen(self.app.devices))
|
||||
event.stop()
|
||||
return # Don't exit the app
|
||||
|
||||
case "find_quiet_button":
|
||||
_PENDING_JOB = ("legacy", findQuietAgents, (self.app.api,), {})
|
||||
|
||||
case "otp_activities_button":
|
||||
_PENDING_JOB = ("legacy", otp_activities_by_agent, (self.app.api,), {})
|
||||
# === FIXED: push the Textual OTPActivitiesScreen and return immediately ===
|
||||
# This must return so we don't fall through to the code that exits the app.
|
||||
self.app.push_screen(OTPActivitiesScreen())
|
||||
event.stop()
|
||||
return
|
||||
|
||||
case "otp_revoke_button":
|
||||
_PENDING_JOB = ("legacy", otp_revoke, (self.app.api,), {})
|
||||
|
||||
case "policy_prep_button":
|
||||
_PENDING_JOB = ("legacy", menu_policy_enforce, (self.app.api,), {})
|
||||
|
||||
case "policy_audit_update_button":
|
||||
_PENDING_JOB = ("legacy", confirmUpdateAfromE, (self.app.api,), {})
|
||||
|
||||
case _:
|
||||
self.app.bell()
|
||||
logger.warning("Unknown button pressed: %s", button_id)
|
||||
return
|
||||
|
||||
# Only exit the UI loop when we explicitly queued a legacy job.
|
||||
# The original flow used `self.app.exit()` after setting _PENDING_JOB so
|
||||
# the outer loop could run legacy code. Keep that behavior only for legacy jobs.
|
||||
logger.debug("Set _PENDING_JOB = %r", _PENDING_JOB)
|
||||
self.app.exit()
|
||||
if _PENDING_JOB and _PENDING_JOB[0] == "legacy":
|
||||
# let the main loop pick up the legacy job
|
||||
self.app.exit()
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 2) APP
|
||||
# ---------------------------------------------------------------------------
|
||||
class Loxide(App):
|
||||
class Loxide(App[Message]):
|
||||
api: AirlockAPIWrapper
|
||||
working_dir: str
|
||||
policies: Optional[list[Policy]]
|
||||
devices: Optional[list[Agent]]
|
||||
|
||||
CSS = """
|
||||
#logo {
|
||||
width: 100%;
|
||||
@@ -398,7 +423,7 @@ class Loxide(App):
|
||||
self.register_theme(get_retro_terminal_theme())
|
||||
self.register_theme(get_amber_terminal_theme())
|
||||
self.theme = self._textual_theme
|
||||
self.push_screen(MainMenuScreen(api))
|
||||
self.push_screen(MainMenuScreen())
|
||||
|
||||
def action_quit(self) -> None:
|
||||
global _PENDING_JOB
|
||||
@@ -406,12 +431,13 @@ class Loxide(App):
|
||||
self.exit()
|
||||
|
||||
def action_open_dir(self) -> None:
|
||||
# Refresh data before proceeding
|
||||
self.refresh_data()
|
||||
screen = self.screen_stack[-1]
|
||||
if isinstance(screen, MainMenuScreen):
|
||||
if screen.current_tab != "dir":
|
||||
screen.switch_tab("dir")
|
||||
"""Open the working directory in the OS file manager (footer binding)."""
|
||||
path_to_open = self.working_dir or os.getcwd()
|
||||
try:
|
||||
open_directory(path_to_open)
|
||||
except Exception as exc:
|
||||
logger.error("Failed to open directory %s: %s", path_to_open, exc)
|
||||
self.bell() # optional feedback
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user