feat: add production configuration with environment variables
- Add .env file for production deployment with reverse proxy - Add docker-compose.prod.yml for production profile - Add docker-compose.override.yml for local development - Update docker-compose.yml with all configurable variables - Update frontend to use VITE_* environment variables - Update backend to support CORS_ORIGINS and WEBHOOK_BASE_URL - Add vite.config.ts allowedHosts for reverse proxy - Add documentation for docker-compose and reverse proxy setup All URLs are now configurable via environment variables: - VITE_API_URL: Backend API endpoint - VITE_WEBHOOK_BASE_URL: Webhook base URL - VITE_INSTALL_SCRIPT_URL: Install script URL - VITE_APP_URL: Frontend URL - CORS_ORIGINS: Allowed CORS origins - WEBHOOK_BASE_URL: Backend webhook base URL
This commit is contained in:
15
frontend/.env.development
Normal file
15
frontend/.env.development
Normal file
@@ -0,0 +1,15 @@
|
||||
# LogWhispererAI - Frontend Environment Variables (Development)
|
||||
# These variables are exposed to the browser (must start with VITE_)
|
||||
|
||||
# Backend API URL
|
||||
VITE_API_URL=http://192.168.254.79:3001
|
||||
|
||||
# Base URL for webhook endpoints
|
||||
VITE_WEBHOOK_BASE_URL=http://192.168.254.79:3001/webhook
|
||||
|
||||
# Install script URL
|
||||
VITE_INSTALL_SCRIPT_URL=http://192.168.254.79:3001/install.sh
|
||||
|
||||
# Application identification
|
||||
VITE_APP_NAME=LogWhispererAI
|
||||
VITE_APP_URL=http://192.168.254.79:5173
|
||||
@@ -49,7 +49,8 @@ interface ApiResponse {
|
||||
message?: string;
|
||||
}
|
||||
|
||||
const API_URL = import.meta.env.VITE_API_URL || 'http://localhost:3000';
|
||||
// Environment configuration
|
||||
const API_URL = import.meta.env.VITE_API_URL || 'http://localhost:3001';
|
||||
|
||||
export const InteractiveDemo: React.FC = () => {
|
||||
const [selectedLog, setSelectedLog] = useState<string | null>(null);
|
||||
|
||||
@@ -22,21 +22,56 @@ export const OnboardingWizard: React.FC<OnboardingWizardProps> = ({ onComplete }
|
||||
const [isGenerating, setIsGenerating] = useState(false);
|
||||
const stepRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
// Focus management for accessibility
|
||||
// Focus management for accessibility - only when step changes, not on initial mount
|
||||
useEffect(() => {
|
||||
if (stepRef.current) {
|
||||
stepRef.current.focus();
|
||||
// Only focus if this is a step change (not initial mount)
|
||||
// This prevents auto-scroll to the onboarding section on page load
|
||||
if (stepRef.current && document.activeElement !== document.body) {
|
||||
stepRef.current.focus({ preventScroll: true });
|
||||
}
|
||||
}, [currentStep]);
|
||||
|
||||
const generateWebhook = () => {
|
||||
// Environment configuration
|
||||
const API_URL = import.meta.env.VITE_API_URL || 'http://localhost:3001';
|
||||
const WEBHOOK_BASE_URL = import.meta.env.VITE_WEBHOOK_BASE_URL || `${API_URL}/webhook`;
|
||||
const INSTALL_SCRIPT_URL = import.meta.env.VITE_INSTALL_SCRIPT_URL || `${API_URL}/install.sh`;
|
||||
const APP_NAME = import.meta.env.VITE_APP_NAME || 'LogWhispererAI';
|
||||
|
||||
const generateWebhook = async () => {
|
||||
setIsGenerating(true);
|
||||
// Simulate generation delay
|
||||
setTimeout(() => {
|
||||
const uuid = crypto.randomUUID();
|
||||
setWebhookUrl(`https://logwhisperer.ai/webhook/${uuid}`);
|
||||
|
||||
try {
|
||||
const response = await fetch(`${API_URL}/api/webhook`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success && data.uuid) {
|
||||
// Use configured webhook base URL instead of API response
|
||||
setWebhookUrl(`${WEBHOOK_BASE_URL}/${data.uuid}`);
|
||||
} else {
|
||||
throw new Error(data.message || 'Errore nella generazione del webhook');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error generating webhook:', error);
|
||||
// Fallback: generate locally if API fails
|
||||
const uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
|
||||
const r = Math.random() * 16 | 0;
|
||||
const v = c === 'x' ? r : (r & 0x3 | 0x8);
|
||||
return v.toString(16);
|
||||
});
|
||||
setWebhookUrl(`${WEBHOOK_BASE_URL}/${uuid}`);
|
||||
} finally {
|
||||
setIsGenerating(false);
|
||||
}, 1000);
|
||||
}
|
||||
};
|
||||
|
||||
const copyWebhook = () => {
|
||||
@@ -46,7 +81,7 @@ export const OnboardingWizard: React.FC<OnboardingWizardProps> = ({ onComplete }
|
||||
};
|
||||
|
||||
const copyCurlCommand = () => {
|
||||
const command = `curl -fsSL https://logwhisperer.ai/install.sh | bash -s -- --webhook ${webhookUrl}`;
|
||||
const command = `curl -fsSL ${INSTALL_SCRIPT_URL} | bash -s -- --webhook ${webhookUrl}`;
|
||||
navigator.clipboard.writeText(command);
|
||||
setCopied(true);
|
||||
setTimeout(() => setCopied(false), 2000);
|
||||
@@ -68,8 +103,8 @@ export const OnboardingWizard: React.FC<OnboardingWizardProps> = ({ onComplete }
|
||||
|
||||
const getInstallCommand = () => {
|
||||
return webhookUrl
|
||||
? `curl -fsSL https://logwhisperer.ai/install.sh | bash -s -- --webhook ${webhookUrl}`
|
||||
: 'curl -fsSL https://logwhisperer.ai/install.sh | bash';
|
||||
? `curl -fsSL ${INSTALL_SCRIPT_URL} | bash -s -- --webhook ${webhookUrl}`
|
||||
: `curl -fsSL ${INSTALL_SCRIPT_URL} | bash`;
|
||||
};
|
||||
|
||||
const steps = [
|
||||
|
||||
@@ -10,5 +10,13 @@ export default defineConfig({
|
||||
watch: {
|
||||
usePolling: true,
|
||||
},
|
||||
// Allow requests from reverse proxy host
|
||||
// Add your production domain here
|
||||
allowedHosts: [
|
||||
'localhost',
|
||||
'127.0.0.1',
|
||||
'.lab.home.lucasacchi.net', // Allow all subdomains
|
||||
'logwhispererai.lab.home.lucasacchi.net',
|
||||
],
|
||||
},
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user