cp
This commit is contained in:
parent
d193f05974
commit
3208307eaa
@ -46,7 +46,7 @@
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#" onclick="showPage('api-keys')">
|
||||
<a class="nav-link" href="#" onclick="showPage('apiKeys')">
|
||||
<i class="fas fa-key me-1"></i>API Keys
|
||||
</a>
|
||||
</li>
|
||||
|
||||
@ -11,9 +11,11 @@ class ApiClient {
|
||||
}
|
||||
|
||||
getHeaders(includeContentType = true) {
|
||||
const headers = {
|
||||
'X-API-Key': this.apiKey
|
||||
};
|
||||
const headers = {};
|
||||
|
||||
if (this.apiKey) {
|
||||
headers['X-API-Key'] = this.apiKey;
|
||||
}
|
||||
|
||||
if (includeContentType) {
|
||||
headers['Content-Type'] = 'application/json';
|
||||
@ -25,8 +27,8 @@ class ApiClient {
|
||||
async makeRequest(method, endpoint, data = null, isFormData = false) {
|
||||
this.updateConfig();
|
||||
|
||||
if (!this.baseUrl || !this.apiKey) {
|
||||
throw new Error('API not configured. Please set API base URL and key.');
|
||||
if (!this.baseUrl) {
|
||||
throw new Error('API not configured. Please set API base URL.');
|
||||
}
|
||||
|
||||
const url = `${this.baseUrl}/api/v1${endpoint}`;
|
||||
|
||||
@ -9,6 +9,7 @@ const app = {
|
||||
|
||||
// Initialize the application
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
console.log('App.js DOMContentLoaded fired');
|
||||
console.log('SeReact Frontend v' + app.version + ' - Initializing...');
|
||||
|
||||
// Initialize configuration
|
||||
@ -184,7 +185,7 @@ function handleRouteChange() {
|
||||
const route = hash || 'home';
|
||||
|
||||
// Validate route
|
||||
const validRoutes = ['home', 'config', 'images', 'search', 'teams', 'users', 'api-keys'];
|
||||
const validRoutes = ['home', 'config', 'images', 'search', 'teams', 'users', 'apiKeys'];
|
||||
|
||||
if (validRoutes.includes(route)) {
|
||||
showPage(route);
|
||||
@ -248,7 +249,7 @@ function setupKeyboardShortcuts() {
|
||||
|
||||
// Number shortcuts for navigation
|
||||
if (e.key >= '1' && e.key <= '6' && !e.ctrlKey && !e.metaKey && !e.altKey) {
|
||||
const pages = ['home', 'images', 'search', 'teams', 'users', 'api-keys'];
|
||||
const pages = ['home', 'images', 'search', 'teams', 'users', 'apiKeys'];
|
||||
const pageIndex = parseInt(e.key) - 1;
|
||||
if (pages[pageIndex]) {
|
||||
e.preventDefault();
|
||||
@ -279,7 +280,7 @@ function refreshCurrentPageData() {
|
||||
case 'users':
|
||||
loadUsers();
|
||||
break;
|
||||
case 'api-keys':
|
||||
case 'apiKeys':
|
||||
loadApiKeys();
|
||||
break;
|
||||
}
|
||||
|
||||
@ -3,6 +3,11 @@ class Config {
|
||||
constructor() {
|
||||
this.apiBaseUrl = localStorage.getItem('apiBaseUrl') || 'http://localhost:8000';
|
||||
this.apiKey = localStorage.getItem('apiKey') || '';
|
||||
|
||||
// Set default configuration if not already set
|
||||
if (!localStorage.getItem('apiBaseUrl')) {
|
||||
this.setApiBaseUrl('http://localhost:8000');
|
||||
}
|
||||
}
|
||||
|
||||
setApiBaseUrl(url) {
|
||||
@ -24,7 +29,7 @@ class Config {
|
||||
}
|
||||
|
||||
isConfigured() {
|
||||
return this.apiBaseUrl && this.apiKey;
|
||||
return this.apiBaseUrl; // Only require base URL, make API key optional for now
|
||||
}
|
||||
|
||||
clear() {
|
||||
@ -82,11 +87,6 @@ async function testConnection() {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!apiKey) {
|
||||
showAlert('API Key is required', 'danger');
|
||||
return;
|
||||
}
|
||||
|
||||
const testButton = document.querySelector('button[onclick="testConnection()"]');
|
||||
const originalText = testButton.innerHTML;
|
||||
testButton.innerHTML = '<span class="loading-spinner"></span> Testing...';
|
||||
@ -105,28 +105,34 @@ async function testConnection() {
|
||||
throw new Error(`Health check failed with status ${healthResponse.status}`);
|
||||
}
|
||||
|
||||
// Test API authentication
|
||||
const authResponse = await fetch(`${apiBaseUrl}/api/v1/teams`, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-API-Key': apiKey
|
||||
// Test API authentication only if API key is provided
|
||||
if (apiKey) {
|
||||
const authResponse = await fetch(`${apiBaseUrl}/api/v1/teams`, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-API-Key': apiKey
|
||||
}
|
||||
});
|
||||
|
||||
if (authResponse.status === 401) {
|
||||
throw new Error('Authentication failed - Invalid API key');
|
||||
} else if (authResponse.status === 403) {
|
||||
throw new Error('Access forbidden - API key lacks permissions');
|
||||
} else if (!authResponse.ok) {
|
||||
throw new Error(`API request failed with status ${authResponse.status}`);
|
||||
}
|
||||
});
|
||||
|
||||
if (authResponse.status === 401) {
|
||||
throw new Error('Authentication failed - Invalid API key');
|
||||
} else if (authResponse.status === 403) {
|
||||
throw new Error('Access forbidden - API key lacks permissions');
|
||||
} else if (!authResponse.ok) {
|
||||
throw new Error(`API request failed with status ${authResponse.status}`);
|
||||
|
||||
showAlert('API connection successful! Backend is up and running with authentication.', 'success');
|
||||
} else {
|
||||
showAlert('API connection successful! Backend is up and running (no authentication tested).', 'success');
|
||||
}
|
||||
|
||||
showAlert('API connection successful! Backend is up and running.', 'success');
|
||||
|
||||
// Save the working configuration
|
||||
config.setApiBaseUrl(apiBaseUrl);
|
||||
config.setApiKey(apiKey);
|
||||
if (apiKey) {
|
||||
config.setApiKey(apiKey);
|
||||
}
|
||||
|
||||
// Update form values
|
||||
document.getElementById('apiBaseUrl').value = apiBaseUrl;
|
||||
|
||||
@ -2,6 +2,11 @@
|
||||
|
||||
// Load teams
|
||||
async function loadTeams() {
|
||||
console.log('loadTeams called');
|
||||
console.log('Config check:', config.isConfigured());
|
||||
console.log('API Base URL:', config.getApiBaseUrl());
|
||||
console.log('API Key:', config.getApiKey() ? 'Set' : 'Not set');
|
||||
|
||||
if (!config.isConfigured()) {
|
||||
showAlert('Please configure your API settings first.', 'warning');
|
||||
return;
|
||||
@ -11,11 +16,15 @@ async function loadTeams() {
|
||||
container.innerHTML = '<div class="text-center"><div class="loading-spinner"></div> Loading teams...</div>';
|
||||
|
||||
try {
|
||||
console.log('Making API request to get teams...');
|
||||
const response = await apiClient.getTeams();
|
||||
console.log('API response:', response);
|
||||
// Handle structured response - extract teams array from response object
|
||||
const teams = response.teams || response;
|
||||
console.log('Teams data:', teams);
|
||||
displayTeams(teams);
|
||||
} catch (error) {
|
||||
console.error('Error loading teams:', error);
|
||||
handleApiError(error, 'loading teams');
|
||||
container.innerHTML = '<div class="alert alert-danger">Failed to load teams</div>';
|
||||
}
|
||||
|
||||
@ -2,14 +2,18 @@
|
||||
|
||||
// Page navigation
|
||||
function showPage(pageId) {
|
||||
console.log('showPage called with pageId:', pageId);
|
||||
|
||||
// Hide all pages
|
||||
const pages = document.querySelectorAll('.page');
|
||||
console.log('Found pages:', pages.length);
|
||||
pages.forEach(page => {
|
||||
page.style.display = 'none';
|
||||
});
|
||||
|
||||
// Show the selected page
|
||||
const targetPage = document.getElementById(pageId + 'Page');
|
||||
console.log('Target page element:', targetPage);
|
||||
if (targetPage) {
|
||||
targetPage.style.display = 'block';
|
||||
|
||||
@ -20,7 +24,10 @@ function showPage(pageId) {
|
||||
updateNavActiveState(pageId);
|
||||
|
||||
// Load page data if needed
|
||||
console.log('Loading page data for:', pageId);
|
||||
loadPageData(pageId);
|
||||
} else {
|
||||
console.error('Target page not found:', pageId + 'Page');
|
||||
}
|
||||
}
|
||||
|
||||
@ -38,25 +45,34 @@ function updateNavActiveState(activePageId) {
|
||||
|
||||
// Load page-specific data
|
||||
function loadPageData(pageId) {
|
||||
console.log('loadPageData called with pageId:', pageId);
|
||||
switch (pageId) {
|
||||
case 'config':
|
||||
console.log('Loading config page');
|
||||
initializeConfigForm();
|
||||
break;
|
||||
case 'images':
|
||||
console.log('Loading images page');
|
||||
loadImages();
|
||||
break;
|
||||
case 'teams':
|
||||
console.log('Loading teams page');
|
||||
loadTeams();
|
||||
break;
|
||||
case 'users':
|
||||
console.log('Loading users page');
|
||||
loadUsers();
|
||||
break;
|
||||
case 'api-keys':
|
||||
case 'apiKeys':
|
||||
console.log('Loading apiKeys page');
|
||||
loadApiKeys();
|
||||
break;
|
||||
case 'search':
|
||||
console.log('Loading search page');
|
||||
initializeSearchForm();
|
||||
break;
|
||||
default:
|
||||
console.log('No specific loader for page:', pageId);
|
||||
}
|
||||
}
|
||||
|
||||
@ -266,6 +282,8 @@ window.addEventListener('hashchange', () => {
|
||||
|
||||
// Initialize page on load
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
console.log('UI.js DOMContentLoaded fired');
|
||||
|
||||
// Initialize tooltips and popovers
|
||||
initializeTooltips();
|
||||
initializePopovers();
|
||||
@ -276,5 +294,25 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
// Show initial page
|
||||
const hash = window.location.hash.substring(1);
|
||||
const initialPage = hash || 'home';
|
||||
console.log('Initial page:', initialPage);
|
||||
showPage(initialPage);
|
||||
});
|
||||
});
|
||||
|
||||
// Test function for debugging
|
||||
function testPageNavigation() {
|
||||
console.log('Testing page navigation...');
|
||||
console.log('Available pages:', document.querySelectorAll('.page').length);
|
||||
|
||||
const pages = ['home', 'config', 'teams', 'users'];
|
||||
pages.forEach(pageId => {
|
||||
const pageElement = document.getElementById(pageId + 'Page');
|
||||
console.log(`Page ${pageId}:`, pageElement ? 'Found' : 'NOT FOUND');
|
||||
});
|
||||
|
||||
// Test showing teams page
|
||||
console.log('Testing showPage("teams")...');
|
||||
showPage('teams');
|
||||
}
|
||||
|
||||
// Make test function available globally
|
||||
window.testPageNavigation = testPageNavigation;
|
||||
@ -2,6 +2,11 @@
|
||||
|
||||
// Load users
|
||||
async function loadUsers() {
|
||||
console.log('loadUsers called');
|
||||
console.log('Config check:', config.isConfigured());
|
||||
console.log('API Base URL:', config.getApiBaseUrl());
|
||||
console.log('API Key:', config.getApiKey() ? 'Set' : 'Not set');
|
||||
|
||||
if (!config.isConfigured()) {
|
||||
showAlert('Please configure your API settings first.', 'warning');
|
||||
return;
|
||||
@ -11,11 +16,15 @@ async function loadUsers() {
|
||||
container.innerHTML = '<div class="text-center"><div class="loading-spinner"></div> Loading users...</div>';
|
||||
|
||||
try {
|
||||
console.log('Making API request to get users...');
|
||||
const response = await apiClient.getUsers();
|
||||
console.log('API response:', response);
|
||||
// Handle structured response - extract users array from response object
|
||||
const users = response.users || response;
|
||||
console.log('Users data:', users);
|
||||
displayUsers(users);
|
||||
} catch (error) {
|
||||
console.error('Error loading users:', error);
|
||||
handleApiError(error, 'loading users');
|
||||
container.innerHTML = '<div class="alert alert-danger">Failed to load users</div>';
|
||||
}
|
||||
|
||||
@ -11,7 +11,7 @@ import sys
|
||||
from pathlib import Path
|
||||
|
||||
# Configuration
|
||||
PORT = 8080
|
||||
PORT = 8081
|
||||
HOST = 'localhost'
|
||||
|
||||
class CustomHTTPRequestHandler(http.server.SimpleHTTPRequestHandler):
|
||||
|
||||
92
client/test.html
Normal file
92
client/test.html
Normal file
@ -0,0 +1,92 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>SeReact Test</title>
|
||||
<style>
|
||||
.page { display: none; padding: 20px; border: 1px solid #ccc; margin: 10px; }
|
||||
.page.active { display: block; }
|
||||
button { margin: 5px; padding: 10px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>SeReact Navigation Test</h1>
|
||||
|
||||
<div>
|
||||
<button onclick="showPage('home')">Home</button>
|
||||
<button onclick="showPage('teams')">Teams</button>
|
||||
<button onclick="showPage('users')">Users</button>
|
||||
<button onclick="showPage('config')">Config</button>
|
||||
<button onclick="testPageNavigation()">Test Navigation</button>
|
||||
</div>
|
||||
|
||||
<div id="homePage" class="page">
|
||||
<h2>Home Page</h2>
|
||||
<p>This is the home page content.</p>
|
||||
</div>
|
||||
|
||||
<div id="teamsPage" class="page">
|
||||
<h2>Teams Page</h2>
|
||||
<div id="teamsContainer">Teams will load here...</div>
|
||||
</div>
|
||||
|
||||
<div id="usersPage" class="page">
|
||||
<h2>Users Page</h2>
|
||||
<div id="usersContainer">Users will load here...</div>
|
||||
</div>
|
||||
|
||||
<div id="configPage" class="page">
|
||||
<h2>Config Page</h2>
|
||||
<p>Configuration settings go here.</p>
|
||||
</div>
|
||||
|
||||
<div id="alertContainer"></div>
|
||||
|
||||
<script>
|
||||
// Simple config mock
|
||||
const config = {
|
||||
isConfigured: () => true,
|
||||
getApiBaseUrl: () => 'http://localhost:8000',
|
||||
getApiKey: () => 'test-key'
|
||||
};
|
||||
|
||||
// Simple API client mock
|
||||
const apiClient = {
|
||||
getTeams: () => Promise.resolve({teams: [{id: '1', name: 'Test Team', description: 'A test team', created_at: new Date().toISOString()}]}),
|
||||
getUsers: () => Promise.resolve({users: [{id: '1', name: 'Test User', email: 'test@example.com', team_id: '1', is_admin: false, created_at: new Date().toISOString()}]})
|
||||
};
|
||||
|
||||
// Mock functions
|
||||
function showAlert(message, type) {
|
||||
console.log(`Alert (${type}): ${message}`);
|
||||
}
|
||||
|
||||
function handleApiError(error, context) {
|
||||
console.error(`API Error ${context}:`, error);
|
||||
}
|
||||
|
||||
function escapeHtml(text) {
|
||||
const div = document.createElement('div');
|
||||
div.textContent = text;
|
||||
return div.innerHTML;
|
||||
}
|
||||
|
||||
function formatDate(dateString) {
|
||||
return new Date(dateString).toLocaleString();
|
||||
}
|
||||
</script>
|
||||
|
||||
<script src="js/ui.js"></script>
|
||||
<script src="js/teams.js"></script>
|
||||
<script src="js/users.js"></script>
|
||||
|
||||
<script>
|
||||
// Initialize on load
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
console.log('Test page loaded');
|
||||
showPage('home');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@ -72,10 +72,7 @@ start_dev_server() {
|
||||
fi
|
||||
|
||||
# Check if Python is available
|
||||
if command -v python3 &> /dev/null; then
|
||||
print_color $BLUE "🐍 Using Python development server"
|
||||
python3 serve.py
|
||||
elif command -v python &> /dev/null; then
|
||||
if command -v python &> /dev/null; then
|
||||
print_color $BLUE "🐍 Using Python development server"
|
||||
python serve.py
|
||||
else
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user