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
146 lines
4.2 KiB
Python
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']
|
|
)
|