new view for containers, authProvider update
This commit is contained in:
parent
69d5082363
commit
8e6b0cc930
|
|
@ -1,11 +1,16 @@
|
|||
import { Stack } from "expo-router";
|
||||
import { AuthProvider } from './context/AuthContext';
|
||||
|
||||
|
||||
export default function RootLayout() {
|
||||
return (
|
||||
<AuthProvider>
|
||||
<Stack
|
||||
screenOptions={{
|
||||
headerTitle: "Portainer Manager"
|
||||
}}
|
||||
/>
|
||||
>
|
||||
</Stack>
|
||||
</AuthProvider>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,117 @@
|
|||
import { Text, View } from 'react-native';
|
||||
import { Text, View, ActivityIndicator } from 'react-native';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useLocalSearchParams, useGlobalSearchParams, Link } from 'expo-router';
|
||||
import { useAuth } from '../context/AuthContext';
|
||||
import { SafeAreaProvider, SafeAreaView } from 'react-native-safe-area-context';
|
||||
import { ScrollView } from 'react-native';
|
||||
|
||||
interface Container {
|
||||
Id: string;
|
||||
Names: string[];
|
||||
Image: string;
|
||||
ImageID: string;
|
||||
Command: string;
|
||||
Created: number;
|
||||
State: string;
|
||||
Status: string;
|
||||
// Add other fields as needed
|
||||
}
|
||||
|
||||
export default function Route() {
|
||||
const glob = useGlobalSearchParams();
|
||||
const local = useLocalSearchParams();
|
||||
const { domain, username, authData } = useAuth();
|
||||
const [containers, setContainers] = useState<Container[]>([]);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
fetchData();
|
||||
}, []); // Empty dependency array means this runs once on mount
|
||||
|
||||
const fetchData = async () => {
|
||||
setIsLoading(true);
|
||||
try {
|
||||
const response = await fetch(`${domain}/api/endpoints/${local.env}/docker/containers/json?all=true`, {
|
||||
headers: {
|
||||
'Authorization': `Bearer ${authData.jwt}`
|
||||
}
|
||||
});
|
||||
const data = await response.json();
|
||||
setContainers(data);
|
||||
} catch (error) {
|
||||
console.error('Error fetching data:', error);
|
||||
setError('Failed to fetch containers');
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<View>
|
||||
<Text>Glob: {local.env}</Text>
|
||||
<Text>Local: {glob.env}</Text>
|
||||
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
|
||||
<ActivityIndicator size="large" color="#0000ff" />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<View>
|
||||
<Text>Error: {error}</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<SafeAreaProvider>
|
||||
<SafeAreaView style={{ flex: 1, padding: 16, width: '100%' }}>
|
||||
<ScrollView showsVerticalScrollIndicator={false}>
|
||||
{containers.map((container) => (
|
||||
<View key={container.Id} style={{
|
||||
padding: 20,
|
||||
marginVertical: 10,
|
||||
backgroundColor: 'rgba(13, 71, 161, 0.1)',
|
||||
borderRadius: 8,
|
||||
borderLeftWidth: 6,
|
||||
borderLeftColor: '#0D47A1',
|
||||
shadowColor: '#000',
|
||||
shadowOffset: {
|
||||
width: 0,
|
||||
height: 2,
|
||||
},
|
||||
shadowOpacity: 0.25,
|
||||
shadowRadius: 3.84,
|
||||
elevation: 5,
|
||||
minHeight: 120,
|
||||
borderWidth: 1,
|
||||
borderColor: 'rgba(13, 71, 161, 0.2)',
|
||||
}}>
|
||||
<Text style={{
|
||||
fontSize: 18,
|
||||
fontWeight: 'bold',
|
||||
color: '#0D47A1',
|
||||
marginBottom: 8
|
||||
}}>{container.Names[0].replace('/', '')}</Text>
|
||||
<Text style={{
|
||||
fontSize: 14,
|
||||
color: '#1976D2',
|
||||
marginBottom: 4
|
||||
}}>Status: {container.Status}</Text>
|
||||
<Text style={{
|
||||
fontSize: 14,
|
||||
color: container.State === 'running' ? '#2E7D32' : '#C62828',
|
||||
marginBottom: 4
|
||||
}}>State: {container.State}</Text>
|
||||
<Text style={{
|
||||
fontSize: 14,
|
||||
color: '#1976D2',
|
||||
marginBottom: 4
|
||||
}}>Image: {container.Image}</Text>
|
||||
</View>
|
||||
))}
|
||||
</ScrollView>
|
||||
</SafeAreaView>
|
||||
</SafeAreaProvider>
|
||||
);
|
||||
}
|
||||
|
|
@ -20,18 +20,15 @@ interface Environment {
|
|||
|
||||
export default function Index() {
|
||||
return (
|
||||
|
||||
<AuthProvider>
|
||||
<View style={{ flex: 1, padding: 16, width: '100%' }}>
|
||||
<MainContent />
|
||||
</View>
|
||||
</AuthProvider>
|
||||
);
|
||||
}
|
||||
|
||||
function MainContent() {
|
||||
const router = useRouter();
|
||||
const { isAuthenticated, domain, username, authData } = useAuth();
|
||||
const { isAuthenticated, domain, username, authData, clearAuth } = useAuth();
|
||||
const [environmentData, setEnvironmentData] = useState<Environment[] | null>(null);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [error, setError] = useState(null);
|
||||
|
|
@ -42,22 +39,35 @@ function MainContent() {
|
|||
|
||||
setIsLoading(true);
|
||||
try {
|
||||
const response = await fetch('https://portainer.evansteele.net/api/endpoints', {
|
||||
const response = await fetch(`${domain}/api/endpoints`, {
|
||||
headers: {
|
||||
'Authorization': `Bearer ${authData.jwt}`
|
||||
}
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
await clearAuth();
|
||||
return;
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (!data) {
|
||||
await clearAuth();
|
||||
return;
|
||||
}
|
||||
|
||||
setEnvironmentData(data);
|
||||
} catch (err : any) {
|
||||
setError(err.message);
|
||||
await clearAuth();
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchEnvironmentData();
|
||||
}, [isAuthenticated]);
|
||||
}, [isAuthenticated, clearAuth]);
|
||||
|
||||
if (!isAuthenticated) {
|
||||
return (
|
||||
|
|
@ -71,7 +81,7 @@ function MainContent() {
|
|||
<SafeAreaProvider>
|
||||
<SafeAreaView style={{ flex: 1, padding: 16, width: '100%' }}>
|
||||
<ScrollView showsVerticalScrollIndicator={false}>
|
||||
{environmentData && environmentData.map((environment, index) => (
|
||||
{Array.isArray(environmentData) && environmentData.map((environment, index) => (
|
||||
<EnvironmentCard
|
||||
key={index}
|
||||
name={environment.Name}
|
||||
|
|
|
|||
Loading…
Reference in New Issue