Ajit Panday commited on
Commit
1a39cdb
·
1 Parent(s): 1b35bfe

Add admin interface for customer management

Browse files
Files changed (2) hide show
  1. app/static/admin.html +197 -0
  2. main.py +6 -18
app/static/admin.html ADDED
@@ -0,0 +1,197 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>vBot Admin Interface</title>
7
+ <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
8
+ <style>
9
+ .container { max-width: 800px; margin-top: 2rem; }
10
+ .customer-list { margin-top: 2rem; }
11
+ .token-section { margin-bottom: 2rem; }
12
+ </style>
13
+ </head>
14
+ <body>
15
+ <div class="container">
16
+ <h1 class="mb-4">vBot Admin Interface</h1>
17
+
18
+ <!-- Login Section -->
19
+ <div class="card token-section">
20
+ <div class="card-body">
21
+ <h5 class="card-title">Admin Login</h5>
22
+ <form id="loginForm">
23
+ <div class="mb-3">
24
+ <label for="username" class="form-label">Username</label>
25
+ <input type="text" class="form-control" id="username" required>
26
+ </div>
27
+ <div class="mb-3">
28
+ <label for="password" class="form-label">Password</label>
29
+ <input type="password" class="form-control" id="password" required>
30
+ </div>
31
+ <button type="submit" class="btn btn-primary">Login</button>
32
+ </form>
33
+ <div id="tokenStatus" class="mt-3"></div>
34
+ </div>
35
+ </div>
36
+
37
+ <!-- Add Customer Section -->
38
+ <div class="card">
39
+ <div class="card-body">
40
+ <h5 class="card-title">Add New Customer</h5>
41
+ <form id="customerForm">
42
+ <div class="mb-3">
43
+ <label for="name" class="form-label">Name</label>
44
+ <input type="text" class="form-control" id="name" required>
45
+ </div>
46
+ <div class="mb-3">
47
+ <label for="company_name" class="form-label">Company Name</label>
48
+ <input type="text" class="form-control" id="company_name" required>
49
+ </div>
50
+ <div class="mb-3">
51
+ <label for="email" class="form-label">Email</label>
52
+ <input type="email" class="form-control" id="email" required>
53
+ </div>
54
+ <button type="submit" class="btn btn-success">Add Customer</button>
55
+ </form>
56
+ <div id="customerStatus" class="mt-3"></div>
57
+ </div>
58
+ </div>
59
+
60
+ <!-- Customer List Section -->
61
+ <div class="card customer-list">
62
+ <div class="card-body">
63
+ <h5 class="card-title">Customer List</h5>
64
+ <div id="customerList" class="table-responsive">
65
+ <table class="table">
66
+ <thead>
67
+ <tr>
68
+ <th>Name</th>
69
+ <th>Company</th>
70
+ <th>Email</th>
71
+ <th>API Key</th>
72
+ <th>Status</th>
73
+ </tr>
74
+ </thead>
75
+ <tbody id="customerTableBody"></tbody>
76
+ </table>
77
+ </div>
78
+ </div>
79
+ </div>
80
+ </div>
81
+
82
+ <script>
83
+ let accessToken = null;
84
+
85
+ // Login Form Handler
86
+ document.getElementById('loginForm').addEventListener('submit', async (e) => {
87
+ e.preventDefault();
88
+ const username = document.getElementById('username').value;
89
+ const password = document.getElementById('password').value;
90
+
91
+ try {
92
+ const response = await fetch('/api/v1/token', {
93
+ method: 'POST',
94
+ headers: {
95
+ 'Content-Type': 'application/x-www-form-urlencoded',
96
+ },
97
+ body: `username=${encodeURIComponent(username)}&password=${encodeURIComponent(password)}`
98
+ });
99
+
100
+ if (response.ok) {
101
+ const data = await response.json();
102
+ accessToken = data.access_token;
103
+ document.getElementById('tokenStatus').innerHTML =
104
+ '<div class="alert alert-success">Login successful!</div>';
105
+ loadCustomers();
106
+ } else {
107
+ document.getElementById('tokenStatus').innerHTML =
108
+ '<div class="alert alert-danger">Login failed. Please check your credentials.</div>';
109
+ }
110
+ } catch (error) {
111
+ document.getElementById('tokenStatus').innerHTML =
112
+ '<div class="alert alert-danger">Error connecting to server.</div>';
113
+ }
114
+ });
115
+
116
+ // Customer Form Handler
117
+ document.getElementById('customerForm').addEventListener('submit', async (e) => {
118
+ e.preventDefault();
119
+ if (!accessToken) {
120
+ document.getElementById('customerStatus').innerHTML =
121
+ '<div class="alert alert-danger">Please login first.</div>';
122
+ return;
123
+ }
124
+
125
+ const customerData = {
126
+ name: document.getElementById('name').value,
127
+ company_name: document.getElementById('company_name').value,
128
+ email: document.getElementById('email').value
129
+ };
130
+
131
+ try {
132
+ const response = await fetch('/api/v1/customers/', {
133
+ method: 'POST',
134
+ headers: {
135
+ 'Authorization': `Bearer ${accessToken}`,
136
+ 'Content-Type': 'application/json'
137
+ },
138
+ body: JSON.stringify(customerData)
139
+ });
140
+
141
+ if (response.ok) {
142
+ const data = await response.json();
143
+ document.getElementById('customerStatus').innerHTML =
144
+ '<div class="alert alert-success">Customer added successfully!</div>';
145
+ document.getElementById('customerForm').reset();
146
+ loadCustomers();
147
+ } else {
148
+ const error = await response.json();
149
+ document.getElementById('customerStatus').innerHTML =
150
+ `<div class="alert alert-danger">Error: ${error.detail}</div>`;
151
+ }
152
+ } catch (error) {
153
+ document.getElementById('customerStatus').innerHTML =
154
+ '<div class="alert alert-danger">Error connecting to server.</div>';
155
+ }
156
+ });
157
+
158
+ // Load Customers
159
+ async function loadCustomers() {
160
+ if (!accessToken) return;
161
+
162
+ try {
163
+ const response = await fetch('/api/v1/customers', {
164
+ headers: {
165
+ 'Authorization': `Bearer ${accessToken}`
166
+ }
167
+ });
168
+
169
+ if (response.ok) {
170
+ const customers = await response.json();
171
+ const tbody = document.getElementById('customerTableBody');
172
+ tbody.innerHTML = '';
173
+
174
+ customers.forEach(customer => {
175
+ const tr = document.createElement('tr');
176
+ tr.innerHTML = `
177
+ <td>${customer.name}</td>
178
+ <td>${customer.company_name}</td>
179
+ <td>${customer.email}</td>
180
+ <td><code>${customer.api_key}</code></td>
181
+ <td>${customer.is_active ? 'Active' : 'Inactive'}</td>
182
+ `;
183
+ tbody.appendChild(tr);
184
+ });
185
+ }
186
+ } catch (error) {
187
+ console.error('Error loading customers:', error);
188
+ }
189
+ }
190
+
191
+ // Initial load if token exists
192
+ if (accessToken) {
193
+ loadCustomers();
194
+ }
195
+ </script>
196
+ </body>
197
+ </html>
main.py CHANGED
@@ -1,6 +1,8 @@
1
  from fastapi import FastAPI, File, UploadFile, HTTPException, Depends, Header, Form, status
2
  from fastapi.middleware.cors import CORSMiddleware
3
  from fastapi.responses import JSONResponse
 
 
4
  from datetime import datetime
5
  import os
6
  from dotenv import load_dotenv
@@ -141,6 +143,9 @@ app.add_middleware(
141
  allow_headers=["*"],
142
  )
143
 
 
 
 
144
  # Initialize Hugging Face models
145
  transcriber = pipeline("automatic-speech-recognition", model=WHISPER_MODEL)
146
  summarizer = pipeline("summarization", model=SUMMARIZER_MODEL)
@@ -152,24 +157,7 @@ app.include_router(auth_router, prefix="/api/v1", tags=["auth"])
152
  @app.get("/")
153
  async def root():
154
  """Root endpoint providing API information"""
155
- return {
156
- "name": "vBot API",
157
- "version": "1.0.0",
158
- "description": "AI-powered call analysis tool for Asterisk-based PBX systems",
159
- "endpoints": {
160
- "process_call": "/api/v1/process-call",
161
- "list_calls": "/api/v1/calls",
162
- "get_call": "/api/v1/calls/{call_id}",
163
- "health_check": "/api/v1/health",
164
- "admin": {
165
- "create_customer": "/api/v1/customers/",
166
- "list_customers": "/api/v1/customers",
167
- "get_customer": "/api/v1/customers/{customer_id}",
168
- "delete_customer": "/api/v1/customers/{customer_id}"
169
- }
170
- },
171
- "documentation": "/docs"
172
- }
173
 
174
  async def get_customer_by_api_key(api_key: str = Header(...), db: Session = Depends(get_db)):
175
  """Get customer by API key"""
 
1
  from fastapi import FastAPI, File, UploadFile, HTTPException, Depends, Header, Form, status
2
  from fastapi.middleware.cors import CORSMiddleware
3
  from fastapi.responses import JSONResponse
4
+ from fastapi.staticfiles import StaticFiles
5
+ from fastapi.responses import FileResponse
6
  from datetime import datetime
7
  import os
8
  from dotenv import load_dotenv
 
143
  allow_headers=["*"],
144
  )
145
 
146
+ # Mount static files
147
+ app.mount("/static", StaticFiles(directory="app/static"), name="static")
148
+
149
  # Initialize Hugging Face models
150
  transcriber = pipeline("automatic-speech-recognition", model=WHISPER_MODEL)
151
  summarizer = pipeline("summarization", model=SUMMARIZER_MODEL)
 
157
  @app.get("/")
158
  async def root():
159
  """Root endpoint providing API information"""
160
+ return FileResponse("app/static/admin.html")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
161
 
162
  async def get_customer_by_api_key(api_key: str = Header(...), db: Session = Depends(get_db)):
163
  """Get customer by API key"""