Files
APIClient-Agent/app/ui/import_dialog.py
Anand Shukla 01662f7e0e Initial release — APIClient - Agent v2.0.0
AI-first API testing desktop client built with Python + PyQt6.

Features:
- Multi-tab HTTP request editor with params/headers/body/auth/tests
- KeyValueTable with per-row enable/disable checkboxes and 36px rows
- Format JSON button, syntax highlighting, pre-request & test scripts
- Collections, environments, history, import/export (Postman v2.1, cURL)
- OpenAPI 3.x / Swagger 2.0 local parser (no AI tokens)
- EKIKA Odoo API Framework generator — JSON-API, REST JSON, GraphQL,
  Custom REST JSON with all auth types (instant, no AI tokens)
- Persistent AI chat sidebar (Claude-powered co-pilot) with streaming,
  context-aware suggestions, and one-click Apply to request editor
- AI collection generator from any docs URL or pasted spec
- WebSocket client, Mock server, Collection runner, Code generator
- Dark/light theme engine (global QSS, object-name selectors)
- SSL error detection with actionable hints
- MIT License

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-28 17:38:57 +05:30

139 lines
4.9 KiB
Python

"""APIClient - Agent — Import Dialog."""
from PyQt6.QtWidgets import (
QDialog, QVBoxLayout, QHBoxLayout, QTabWidget, QWidget,
QTextEdit, QPushButton, QLabel, QFileDialog, QMessageBox
)
from PyQt6.QtGui import QFont
from app.ui.theme import Colors
from app.core import importer, storage
from app.models import HttpRequest
class ImportDialog(QDialog):
def __init__(self, parent=None):
super().__init__(parent)
self.setWindowTitle("Import")
self.setMinimumSize(640, 460)
self.imported_req: HttpRequest | None = None
layout = QVBoxLayout(self)
layout.setContentsMargins(0, 0, 0, 0)
layout.setSpacing(0)
# Header
header = QWidget()
header.setObjectName("panelHeader")
header.setFixedHeight(48)
hl = QHBoxLayout(header)
hl.setContentsMargins(16, 0, 16, 0)
title = QLabel("Import")
title.setObjectName("panelTitle")
hl.addWidget(title)
layout.addWidget(header)
self.tabs = QTabWidget()
self.tabs.addTab(self._make_postman_tab(), "Postman Collection")
self.tabs.addTab(self._make_curl_tab(), "cURL Command")
layout.addWidget(self.tabs, 1)
# ── Tab builders ──────────────────────────────────────────────────────────
def _make_postman_tab(self):
w = QWidget()
layout = QVBoxLayout(w)
layout.setContentsMargins(16, 12, 16, 12)
layout.setSpacing(8)
hint = QLabel("Paste a Postman Collection v2.1 JSON or load from file:")
hint.setObjectName("hintText")
layout.addWidget(hint)
self.postman_editor = QTextEdit()
self.postman_editor.setFont(
QFont("JetBrains Mono, Fira Code, Consolas, monospace", 10)
)
self.postman_editor.setPlaceholderText(
'{\n "info": {"name": "My Collection"},\n "item": [...]\n}'
)
layout.addWidget(self.postman_editor)
btn_row = QHBoxLayout()
load_btn = QPushButton("Load File…")
load_btn.clicked.connect(self._load_postman_file)
import_btn = QPushButton("Import Collection")
import_btn.setObjectName("accent")
import_btn.clicked.connect(self._import_postman)
btn_row.addWidget(load_btn)
btn_row.addStretch()
btn_row.addWidget(import_btn)
layout.addLayout(btn_row)
return w
def _make_curl_tab(self):
w = QWidget()
layout = QVBoxLayout(w)
layout.setContentsMargins(16, 12, 16, 12)
layout.setSpacing(8)
hint = QLabel("Paste a cURL command — it will open as a new request tab:")
hint.setObjectName("hintText")
layout.addWidget(hint)
self.curl_editor = QTextEdit()
self.curl_editor.setFont(
QFont("JetBrains Mono, Fira Code, Consolas, monospace", 10)
)
self.curl_editor.setPlaceholderText(
"curl -X POST https://api.example.com/data \\\n"
" -H 'Content-Type: application/json' \\\n"
" -d '{\"key\": \"value\"}'"
)
layout.addWidget(self.curl_editor)
btn_row = QHBoxLayout()
import_btn = QPushButton("Import as Request")
import_btn.setObjectName("accent")
import_btn.clicked.connect(self._import_curl)
btn_row.addStretch()
btn_row.addWidget(import_btn)
layout.addLayout(btn_row)
return w
# ── Import actions ────────────────────────────────────────────────────────
def _load_postman_file(self):
path, _ = QFileDialog.getOpenFileName(
self, "Open Collection", "", "JSON Files (*.json);;All Files (*)"
)
if path:
with open(path, "r", encoding="utf-8") as f:
self.postman_editor.setPlainText(f.read())
def _import_postman(self):
text = self.postman_editor.toPlainText().strip()
if not text:
return
try:
col_name, requests = importer.from_postman_collection(text)
col_id = storage.add_collection(col_name)
for req in requests:
storage.save_request(col_id, req)
QMessageBox.information(
self, "Import Successful",
f"Imported collection '{col_name}' with {len(requests)} request(s)."
)
self.accept()
except Exception as e:
QMessageBox.critical(self, "Import Error", str(e))
def _import_curl(self):
text = self.curl_editor.toPlainText().strip()
if not text:
return
try:
self.imported_req = importer.from_curl(text)
self.accept()
except Exception as e:
QMessageBox.critical(self, "Import Error", str(e))