311 lines
7.9 KiB
Markdown
311 lines
7.9 KiB
Markdown
# TicketHub - Developer Guide
|
|
|
|
## Overview
|
|
|
|
TicketHub is a lightweight, enterprise-grade open-source ticket and issue tracking system. Built with a modern React frontend and Python FastAPI backend.
|
|
|
|
## Architecture
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ TicketHub │
|
|
├─────────────────────────────────────────────────────────────┤
|
|
│ │
|
|
│ ┌───────────────────────────────────────────────────────┐ │
|
|
│ │ Frontend (React) │ │
|
|
│ │ Dashboard │ Tickets │ Board │ Projects │ Settings │ │
|
|
│ └─────────────────────────┬─────────────────────────────┘ │
|
|
│ │ │
|
|
│ REST API │
|
|
│ │ │
|
|
│ ┌─────────────────────────▼─────────────────────────────┐ │
|
|
│ │ Backend (FastAPI) │ │
|
|
│ │ /api/projects │ /api/tickets │ /api/webhooks │ │
|
|
│ └─────────────────────────┬─────────────────────────────┘ │
|
|
│ │ │
|
|
│ ┌─────────────────────────▼─────────────────────────────┐ │
|
|
│ │ SQLite Database │ │
|
|
│ └───────────────────────────────────────────────────────┘ │
|
|
│ │
|
|
└─────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
## Tech Stack
|
|
|
|
### Frontend
|
|
- **React 18** - UI library
|
|
- **TypeScript** - Type safety
|
|
- **TailwindCSS** - Styling
|
|
- **React Router** - Navigation
|
|
- **React Query** - Data fetching
|
|
- **Vite** - Build tool
|
|
|
|
### Backend
|
|
- **Python 3.11** - Language
|
|
- **FastAPI** - Web framework
|
|
- **SQLite** - Database (dev)
|
|
- **PostgreSQL** - Database (prod)
|
|
|
|
## Project Structure
|
|
|
|
```
|
|
tickethub/
|
|
├── backend/
|
|
│ └── app/
|
|
│ └── main.py # FastAPI application
|
|
├── frontend/
|
|
│ ├── src/
|
|
│ │ ├── components/
|
|
│ │ │ ├── ui/ # Reusable UI components
|
|
│ │ │ └── Layout.tsx # Main layout
|
|
│ │ ├── pages/ # Route pages
|
|
│ │ ├── services/
|
|
│ │ │ └── api.ts # API client
|
|
│ │ ├── App.tsx # Router setup
|
|
│ │ └── main.tsx # Entry point
|
|
│ ├── index.html
|
|
│ ├── package.json
|
|
│ ├── tailwind.config.js
|
|
│ └── vite.config.ts
|
|
├── docs/
|
|
└── README.md
|
|
```
|
|
|
|
## Frontend Development
|
|
|
|
### Component Library
|
|
|
|
TicketHub includes a custom component library:
|
|
|
|
```typescript
|
|
// Available components
|
|
import {
|
|
Card,
|
|
Button,
|
|
Input,
|
|
Select,
|
|
Badge,
|
|
Modal,
|
|
Tabs, TabsList, TabsTrigger, TabsContent,
|
|
Table, TableHeader, TableHead, TableBody, TableRow, TableCell,
|
|
Avatar
|
|
} from '../components/ui'
|
|
```
|
|
|
|
### Adding a New Page
|
|
|
|
1. Create component in `src/pages/`:
|
|
|
|
```typescript
|
|
// src/pages/MyPage.tsx
|
|
import { Card, Button } from '../components/ui'
|
|
|
|
export default function MyPage() {
|
|
return (
|
|
<div className="p-6">
|
|
<h1 className="text-2xl font-bold">My Page</h1>
|
|
<Card>
|
|
<p>Content here</p>
|
|
</Card>
|
|
</div>
|
|
)
|
|
}
|
|
```
|
|
|
|
2. Add route in `App.tsx`:
|
|
|
|
```typescript
|
|
import MyPage from './pages/MyPage'
|
|
|
|
// Inside Routes
|
|
<Route path="mypage" element={<MyPage />} />
|
|
```
|
|
|
|
3. Add to sidebar in `Layout.tsx`
|
|
|
|
### API Integration
|
|
|
|
Use React Query for data fetching:
|
|
|
|
```typescript
|
|
import { useQuery, useMutation } from '@tanstack/react-query'
|
|
import { ticketsApi } from '../services/api'
|
|
|
|
function MyComponent() {
|
|
// Fetch data
|
|
const { data: tickets, isLoading } = useQuery({
|
|
queryKey: ['tickets'],
|
|
queryFn: () => ticketsApi.list()
|
|
})
|
|
|
|
// Mutate data
|
|
const createMutation = useMutation({
|
|
mutationFn: ticketsApi.create,
|
|
onSuccess: () => queryClient.invalidateQueries(['tickets'])
|
|
})
|
|
}
|
|
```
|
|
|
|
## Backend Development
|
|
|
|
### API Structure
|
|
|
|
```python
|
|
# Models
|
|
class Ticket(BaseModel):
|
|
id: int
|
|
key: str
|
|
project_id: int
|
|
title: str
|
|
description: str
|
|
status: Literal['open', 'in_progress', 'resolved', 'closed']
|
|
priority: Literal['low', 'medium', 'high', 'critical']
|
|
assignee: Optional[str]
|
|
reporter: Optional[str]
|
|
created_at: datetime
|
|
updated_at: datetime
|
|
|
|
# Endpoints
|
|
GET /api/projects
|
|
POST /api/projects
|
|
GET /api/projects/{id}
|
|
PATCH /api/projects/{id}
|
|
DELETE /api/projects/{id}
|
|
|
|
GET /api/tickets
|
|
POST /api/tickets
|
|
GET /api/tickets/{id}
|
|
PATCH /api/tickets/{id}
|
|
DELETE /api/tickets/{id}
|
|
|
|
GET /api/tickets/{id}/comments
|
|
POST /api/tickets/{id}/comments
|
|
```
|
|
|
|
### Adding a New Endpoint
|
|
|
|
```python
|
|
@app.post("/api/myresource")
|
|
async def create_myresource(data: MyModel):
|
|
# Validate
|
|
# Save to database
|
|
# Return response
|
|
return {"id": new_id, **data.dict()}
|
|
```
|
|
|
|
### Webhook System
|
|
|
|
TicketHub sends webhooks on ticket events:
|
|
|
|
```python
|
|
async def send_webhook(project_id: int, event: str, data: dict):
|
|
project = await get_project(project_id)
|
|
if project.webhook_url:
|
|
payload = {
|
|
"event": event, # ticket.created, ticket.updated, etc.
|
|
"timestamp": datetime.utcnow().isoformat(),
|
|
"data": data
|
|
}
|
|
await httpx.post(project.webhook_url, json=payload)
|
|
```
|
|
|
|
## Running Locally
|
|
|
|
### Backend
|
|
|
|
```bash
|
|
cd backend
|
|
pip install -r requirements.txt
|
|
uvicorn app.main:app --reload --port 8001
|
|
```
|
|
|
|
### Frontend
|
|
|
|
```bash
|
|
cd frontend
|
|
npm install
|
|
npm run dev
|
|
```
|
|
|
|
### Full Stack (Development)
|
|
|
|
```bash
|
|
# Terminal 1: Backend
|
|
cd backend && uvicorn app.main:app --reload --port 8001
|
|
|
|
# Terminal 2: Frontend (proxies /api to backend)
|
|
cd frontend && npm run dev
|
|
```
|
|
|
|
## Building for Production
|
|
|
|
### Frontend Build
|
|
|
|
```bash
|
|
cd frontend
|
|
npm run build
|
|
# Output: dist/
|
|
```
|
|
|
|
### Docker Deploy
|
|
|
|
```yaml
|
|
version: '3.8'
|
|
services:
|
|
api:
|
|
image: python:3.11-slim
|
|
command: uvicorn app.main:app --host 0.0.0.0 --port 8000
|
|
|
|
web:
|
|
image: nginx:alpine
|
|
volumes:
|
|
- ./frontend/dist:/usr/share/nginx/html
|
|
```
|
|
|
|
## Testing
|
|
|
|
### Backend Tests
|
|
|
|
```bash
|
|
cd backend
|
|
pytest tests/
|
|
```
|
|
|
|
### Frontend Tests
|
|
|
|
```bash
|
|
cd frontend
|
|
npm test
|
|
```
|
|
|
|
### API Testing
|
|
|
|
```bash
|
|
# Create project
|
|
curl -X POST http://localhost:8001/api/projects \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"name": "Test Project", "key": "TEST"}'
|
|
|
|
# Create ticket
|
|
curl -X POST http://localhost:8001/api/tickets \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"project_id": 1,
|
|
"title": "Test ticket",
|
|
"description": "Test description",
|
|
"priority": "medium"
|
|
}'
|
|
```
|
|
|
|
## Contributing
|
|
|
|
1. Fork the repository
|
|
2. Create feature branch: `git checkout -b feature/my-feature`
|
|
3. Make changes
|
|
4. Run tests
|
|
5. Submit pull request
|
|
|
|
## License
|
|
|
|
MIT License - StartData 2026
|