handle errors better
This commit is contained in:
23
app.py
23
app.py
@@ -282,6 +282,12 @@ class SessionMoverApp(App):
|
|||||||
color: $text;
|
color: $text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#current-selection.error {
|
||||||
|
background: $error;
|
||||||
|
color: $text;
|
||||||
|
text-style: bold;
|
||||||
|
}
|
||||||
|
|
||||||
#selection-count {
|
#selection-count {
|
||||||
height: auto;
|
height: auto;
|
||||||
padding: 1;
|
padding: 1;
|
||||||
@@ -385,10 +391,13 @@ class SessionMoverApp(App):
|
|||||||
self.db.connect()
|
self.db.connect()
|
||||||
self.db.load_reference_data()
|
self.db.load_reference_data()
|
||||||
except FileNotFoundError as e:
|
except FileNotFoundError as e:
|
||||||
self.notify(str(e), severity="error", timeout=10)
|
widget = self.query_one("#current-selection", Static)
|
||||||
self.set_timer(1, self.exit)
|
widget.add_class("error")
|
||||||
|
widget.update(f"Error: {e}\n\nPress q to quit.")
|
||||||
|
self._db_error = True
|
||||||
return
|
return
|
||||||
|
|
||||||
|
self._db_error = False
|
||||||
self._project_ids: List[str] = []
|
self._project_ids: List[str] = []
|
||||||
self.refresh_project_list()
|
self.refresh_project_list()
|
||||||
|
|
||||||
@@ -398,15 +407,14 @@ class SessionMoverApp(App):
|
|||||||
self.query_one("#archived-toggle", Button).can_focus = False
|
self.query_one("#archived-toggle", Button).can_focus = False
|
||||||
|
|
||||||
# Setup sessions table (but don't load data yet)
|
# Setup sessions table (but don't load data yet)
|
||||||
table = self.query_one("#sessions-table")
|
table = self.query_one("#sessions-table", DataTable)
|
||||||
table.zebra_stripes = True
|
table.zebra_stripes = True
|
||||||
table.cursor_type = "row"
|
table.cursor_type = "row"
|
||||||
table.show_cursor = False
|
table.show_cursor = False
|
||||||
table.add_columns(" ", "ID", "Title", "Project", "Workspace", "Msgs", "Created")
|
table.add_columns(" ", "ID", "Title", "Project", "Workspace", "Msgs", "Created")
|
||||||
|
|
||||||
# Don't load sessions until a project is selected
|
# Don't load sessions until a project is selected
|
||||||
status = self.query_one("#current-selection")
|
self.query_one("#current-selection", Static).update("Select a project from the left")
|
||||||
status.update("Select a project from the left")
|
|
||||||
|
|
||||||
def on_input_changed(self, event: Input.Changed) -> None:
|
def on_input_changed(self, event: Input.Changed) -> None:
|
||||||
if event.input.id == "filter-input":
|
if event.input.id == "filter-input":
|
||||||
@@ -655,6 +663,11 @@ class SessionMoverApp(App):
|
|||||||
self.refresh_sessions()
|
self.refresh_sessions()
|
||||||
self.notify("Data refreshed", severity="information")
|
self.notify("Data refreshed", severity="information")
|
||||||
|
|
||||||
|
async def action_quit(self) -> None:
|
||||||
|
"""Exit the app, with a non-zero return code if there was a DB error."""
|
||||||
|
return_code = 1 if getattr(self, "_db_error", False) else 0
|
||||||
|
self.exit(return_code)
|
||||||
|
|
||||||
def on_unmount(self) -> None:
|
def on_unmount(self) -> None:
|
||||||
"""Cleanup on exit."""
|
"""Cleanup on exit."""
|
||||||
self.db.close()
|
self.db.close()
|
||||||
|
|||||||
18
database.py
18
database.py
@@ -74,7 +74,8 @@ class Database:
|
|||||||
|
|
||||||
def load_reference_data(self):
|
def load_reference_data(self):
|
||||||
"""Load projects and workspaces into memory for fast lookups."""
|
"""Load projects and workspaces into memory for fast lookups."""
|
||||||
assert self.conn is not None
|
if self.conn is None:
|
||||||
|
raise RuntimeError("Database is not connected. Call connect() first.")
|
||||||
cursor = self.conn.cursor()
|
cursor = self.conn.cursor()
|
||||||
|
|
||||||
# Load projects
|
# Load projects
|
||||||
@@ -125,7 +126,8 @@ class Database:
|
|||||||
Returns:
|
Returns:
|
||||||
List of Session objects with computed counts
|
List of Session objects with computed counts
|
||||||
"""
|
"""
|
||||||
assert self.conn is not None, "Database not connected"
|
if self.conn is None:
|
||||||
|
raise RuntimeError("Database is not connected. Call connect() first.")
|
||||||
cursor = self.conn.cursor()
|
cursor = self.conn.cursor()
|
||||||
|
|
||||||
query = """
|
query = """
|
||||||
@@ -205,7 +207,8 @@ class Database:
|
|||||||
|
|
||||||
def get_session_counts_by_project(self) -> dict:
|
def get_session_counts_by_project(self) -> dict:
|
||||||
"""Return a dict of project_id -> active session count."""
|
"""Return a dict of project_id -> active session count."""
|
||||||
assert self.conn is not None
|
if self.conn is None:
|
||||||
|
raise RuntimeError("Database is not connected. Call connect() first.")
|
||||||
cursor = self.conn.cursor()
|
cursor = self.conn.cursor()
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"SELECT project_id, COUNT(*) FROM session WHERE time_archived IS NULL GROUP BY project_id"
|
"SELECT project_id, COUNT(*) FROM session WHERE time_archived IS NULL GROUP BY project_id"
|
||||||
@@ -228,7 +231,8 @@ class Database:
|
|||||||
Returns:
|
Returns:
|
||||||
(success, list of SQL statements executed)
|
(success, list of SQL statements executed)
|
||||||
"""
|
"""
|
||||||
assert self.conn is not None, "Database not connected"
|
if self.conn is None:
|
||||||
|
raise RuntimeError("Database is not connected. Call connect() first.")
|
||||||
cursor = self.conn.cursor()
|
cursor = self.conn.cursor()
|
||||||
|
|
||||||
# Verify target project exists
|
# Verify target project exists
|
||||||
@@ -265,7 +269,8 @@ class Database:
|
|||||||
Returns:
|
Returns:
|
||||||
(success, list of SQL statements, list of new session IDs)
|
(success, list of SQL statements, list of new session IDs)
|
||||||
"""
|
"""
|
||||||
assert self.conn is not None, "Database not connected"
|
if self.conn is None:
|
||||||
|
raise RuntimeError("Database is not connected. Call connect() first.")
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
cursor = self.conn.cursor()
|
cursor = self.conn.cursor()
|
||||||
@@ -355,7 +360,8 @@ class Database:
|
|||||||
Returns:
|
Returns:
|
||||||
(success, error_message)
|
(success, error_message)
|
||||||
"""
|
"""
|
||||||
assert self.conn is not None, "Database not connected"
|
if self.conn is None:
|
||||||
|
raise RuntimeError("Database is not connected. Call connect() first.")
|
||||||
cursor = self.conn.cursor()
|
cursor = self.conn.cursor()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|||||||
0
session-mover.py
Normal file → Executable file
0
session-mover.py
Normal file → Executable file
Reference in New Issue
Block a user