roster/src/models.py
Pavel Baksy ecc9094514 Add left sidebar for managing saved requests in projects
Implement a 3-column layout with a collapsible sidebar for organizing
and managing HTTP requests within projects. Requests are stored in
~/.roster/requests.json for easy git versioning.

Features:
- Create, rename, and delete projects
- Save current request to a project with custom name
- Load saved requests with direct click (no confirmation dialog)
- Delete saved requests with confirmation
- Expandable/collapsible project folders
- Context menu for project actions

Technical changes:
- Add SavedRequest and Project data models with JSON serialization
- Implement ProjectManager for persistence to ~/.roster/requests.json
- Create RequestItem and ProjectItem widgets with GTK templates
- Restructure main window UI to nested GtkPaned (3-column layout)
- Add project management dialogs using AdwAlertDialog
- Update build system with new source files and UI resources
2025-12-18 15:16:21 +01:00

146 lines
4.2 KiB
Python

# models.py
#
# Copyright 2025 Pavel Baksy
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#
# SPDX-License-Identifier: GPL-3.0-or-later
from dataclasses import dataclass, asdict
from typing import Dict, Optional, List
@dataclass
class HttpRequest:
"""Represents an HTTP request."""
method: str # "GET", "POST", "PUT", "DELETE"
url: str
headers: Dict[str, str] # Key-value pairs
body: str # Raw text body
def to_dict(self):
"""Convert to dictionary for JSON serialization."""
return asdict(self)
@classmethod
def from_dict(cls, data):
"""Create instance from dictionary."""
return cls(**data)
@dataclass
class HttpResponse:
"""Represents an HTTP response."""
status_code: int
status_text: str # e.g., "OK"
headers: str # Raw header text from HTTPie
body: str # Raw body text
response_time_ms: float
def to_dict(self):
"""Convert to dictionary for JSON serialization."""
return asdict(self)
@classmethod
def from_dict(cls, data):
"""Create instance from dictionary."""
return cls(**data)
@dataclass
class HistoryEntry:
"""Represents a request/response pair in history."""
timestamp: str # ISO format datetime
request: HttpRequest
response: Optional[HttpResponse]
error: Optional[str] # Error message if request failed
def to_dict(self):
"""Convert to dictionary for JSON serialization."""
return {
'timestamp': self.timestamp,
'request': self.request.to_dict(),
'response': self.response.to_dict() if self.response else None,
'error': self.error
}
@classmethod
def from_dict(cls, data):
"""Create instance from dictionary."""
return cls(
timestamp=data['timestamp'],
request=HttpRequest.from_dict(data['request']),
response=HttpResponse.from_dict(data['response']) if data.get('response') else None,
error=data.get('error')
)
@dataclass
class SavedRequest:
"""A saved HTTP request with metadata."""
id: str # UUID
name: str # User-provided name
request: HttpRequest
created_at: str # ISO format
modified_at: str # ISO format
def to_dict(self):
"""Convert to dictionary for JSON serialization."""
return {
'id': self.id,
'name': self.name,
'request': self.request.to_dict(),
'created_at': self.created_at,
'modified_at': self.modified_at
}
@classmethod
def from_dict(cls, data):
"""Create instance from dictionary."""
return cls(
id=data['id'],
name=data['name'],
request=HttpRequest.from_dict(data['request']),
created_at=data['created_at'],
modified_at=data['modified_at']
)
@dataclass
class Project:
"""A project containing saved requests."""
id: str # UUID
name: str
requests: List[SavedRequest]
created_at: str # ISO format
def to_dict(self):
"""Convert to dictionary for JSON serialization."""
return {
'id': self.id,
'name': self.name,
'requests': [req.to_dict() for req in self.requests],
'created_at': self.created_at
}
@classmethod
def from_dict(cls, data):
"""Create instance from dictionary."""
return cls(
id=data['id'],
name=data['name'],
requests=[SavedRequest.from_dict(r) for r in data.get('requests', [])],
created_at=data['created_at']
)