Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions server.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
parser.add_argument(
"--host",
type=str,
default="localhost",
help="Host to bind the server to (default: localhost)",
default="0.0.0.0",
help="Host to bind the server to (default: 0.0.0.0)",
)
parser.add_argument(
"--port",
Expand Down
5 changes: 5 additions & 0 deletions src/server/app/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@
# ============================================================================
import logging
import os
import certifi

os.environ["SSL_CERT_FILE"] = certifi.where()
os.environ["REQUESTS_CA_BUNDLE"] = certifi.where()

from contextlib import asynccontextmanager
from uuid import uuid4

Expand Down
27 changes: 27 additions & 0 deletions web/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"@radix-ui/react-dialog": "^1.1.15",
"@radix-ui/react-toast": "^1.2.5",
"@supabase/supabase-js": "^2.95.3",
"@tanstack/react-query": "^5.90.21",
"antd": "^5.12.0",
"axios": "^1.7.0",
"class-variance-authority": "^0.7.1",
Expand Down
34 changes: 24 additions & 10 deletions web/src/main.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,25 @@ import React from 'react'
import ReactDOM from 'react-dom/client'
import { BrowserRouter } from 'react-router-dom'
import { ConfigProvider, theme as antdTheme } from 'antd'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { ThemeProvider, useTheme } from './contexts/ThemeContext'
import { AuthProvider } from './contexts/AuthContext'
import App from './App.jsx'
import './i18n'
import './index.css'
import { Toaster } from './components/ui/toaster'

// Initialize a global QueryClient for data fetching and caching
const queryClient = new QueryClient({
defaultOptions: {
queries: {
refetchOnWindowFocus: true, // Auto-refetch when user comes back to the tab
retry: 1, // Retry failed requests once before showing error
staleTime: 1000 * 60 * 2, // Data is considered fresh for 2 minutes by default
},
},
})

function AntdThemeProvider({ children }) {
const { theme } = useTheme()
return (
Expand All @@ -23,14 +35,16 @@ function AntdThemeProvider({ children }) {
}

ReactDOM.createRoot(document.getElementById('root')).render(
<BrowserRouter future={{ v7_startTransition: true, v7_relativeSplatPath: true }}>
<ThemeProvider>
<AntdThemeProvider>
<AuthProvider>
<App />
<Toaster />
</AuthProvider>
</AntdThemeProvider>
</ThemeProvider>
</BrowserRouter>,
<QueryClientProvider client={queryClient}>
<BrowserRouter future={{ v7_startTransition: true, v7_relativeSplatPath: true }}>
<ThemeProvider>
<AntdThemeProvider>
<AuthProvider>
<App />
<Toaster />
</AuthProvider>
</AntdThemeProvider>
</ThemeProvider>
</BrowserRouter>
</QueryClientProvider>,
)
39 changes: 11 additions & 28 deletions web/src/pages/Automations/hooks/useAutomations.js
Original file line number Diff line number Diff line change
@@ -1,38 +1,21 @@
import { useState, useEffect, useCallback, useRef } from 'react';
import { useQuery } from '@tanstack/react-query';
import { listAutomations } from '../utils/api';

const POLL_INTERVAL = 30000;

export function useAutomations({ status } = {}) {
const [automations, setAutomations] = useState([]);
const [total, setTotal] = useState(0);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
const intervalRef = useRef(null);

const fetch = useCallback(async (showLoading = false) => {
if (showLoading) setLoading(true);
try {
const { data = { automations: [], total: 0 }, isLoading: loading, error, refetch } = useQuery({
queryKey: ['automations', status],
queryFn: async () => {
const params = { limit: 100, offset: 0 };
if (status) params.status = status;
const { data } = await listAutomations(params);
setAutomations(data.automations);
setTotal(data.total);
setError(null);
} catch (err) {
setError(err);
} finally {
setLoading(false);
}
}, [status]);

const refetch = useCallback(() => fetch(false), [fetch]);

useEffect(() => {
fetch(true);
intervalRef.current = setInterval(() => fetch(false), POLL_INTERVAL);
return () => clearInterval(intervalRef.current);
}, [fetch]);
return { automations: data.automations, total: data.total };
},
refetchInterval: POLL_INTERVAL,
refetchIntervalInBackground: false,
staleTime: 5000,
});

return { automations, total, loading, error, refetch };
return { automations: data.automations, total: data.total, loading, error, refetch };
}
42 changes: 12 additions & 30 deletions web/src/pages/Automations/hooks/useExecutions.js
Original file line number Diff line number Diff line change
@@ -1,38 +1,20 @@
import { useState, useEffect, useCallback, useRef } from 'react';
import { useQuery } from '@tanstack/react-query';
import { listExecutions } from '../utils/api';

const POLL_INTERVAL = 15000;

export function useExecutions(automationId) {
const [executions, setExecutions] = useState([]);
const [total, setTotal] = useState(0);
const [loading, setLoading] = useState(false);
const intervalRef = useRef(null);

const fetch = useCallback(async (showLoading = false) => {
if (!automationId) return;
if (showLoading) setLoading(true);
try {
const { data = { executions: [], total: 0 }, isLoading: loading } = useQuery({
queryKey: ['executions', automationId],
queryFn: async () => {
const { data } = await listExecutions(automationId, { limit: 20, offset: 0 });
setExecutions(data.executions);
setTotal(data.total);
} catch {
// silently fail on polling
} finally {
setLoading(false);
}
}, [automationId]);

useEffect(() => {
if (!automationId) {
setExecutions([]);
setTotal(0);
return;
}
fetch(true);
intervalRef.current = setInterval(() => fetch(false), POLL_INTERVAL);
return () => clearInterval(intervalRef.current);
}, [automationId, fetch]);
return { executions: data.executions, total: data.total };
},
enabled: !!automationId,
refetchInterval: POLL_INTERVAL,
refetchIntervalInBackground: false,
staleTime: 5000,
});

return { executions, total, loading };
return { executions: data.executions, total: data.total, loading };
}
Loading