initial project setup
This commit is contained in:
147
frontend/src/components/Dashboard.js
Normal file
147
frontend/src/components/Dashboard.js
Normal file
@@ -0,0 +1,147 @@
|
||||
import React from 'react';
|
||||
import { Row, Col, Card, Statistic, Progress, List, Typography } from 'antd';
|
||||
import {
|
||||
DashboardOutlined,
|
||||
ServerOutlined,
|
||||
DatabaseOutlined,
|
||||
WifiOutlined,
|
||||
CheckCircleOutlined,
|
||||
ExclamationCircleOutlined
|
||||
} from '@ant-design/icons';
|
||||
import SystemMetrics from './SystemMetrics';
|
||||
|
||||
const { Title, Text } = Typography;
|
||||
|
||||
const Dashboard = () => {
|
||||
// Mock data - in real app, this would come from API
|
||||
const systemStats = {
|
||||
cpu: 45.2,
|
||||
memory: 68.5,
|
||||
disk: 32.1,
|
||||
network: 12.3
|
||||
};
|
||||
|
||||
const services = [
|
||||
{ name: 'Home Assistant', status: 'online', uptime: '7d 12h' },
|
||||
{ name: 'Frigate', status: 'online', uptime: '7d 12h' },
|
||||
{ name: 'Immich', status: 'online', uptime: '7d 12h' },
|
||||
{ name: 'n8n', status: 'offline', uptime: '0d 0h' },
|
||||
{ name: 'PostgreSQL', status: 'online', uptime: '7d 12h' },
|
||||
{ name: 'Redis', status: 'online', uptime: '7d 12h' }
|
||||
];
|
||||
|
||||
const recentEvents = [
|
||||
{ time: '2 minutes ago', event: 'Person detected at front door', service: 'Frigate' },
|
||||
{ time: '5 minutes ago', event: 'CPU usage above 80%', service: 'System' },
|
||||
{ time: '12 minutes ago', event: 'Alice arrived home', service: 'Home Assistant' },
|
||||
{ time: '1 hour ago', event: 'New photo uploaded', service: 'Immich' }
|
||||
];
|
||||
|
||||
const getStatusIcon = (status) => {
|
||||
return status === 'online' ?
|
||||
<CheckCircleOutlined style={{ color: '#52c41a' }} /> :
|
||||
<ExclamationCircleOutlined style={{ color: '#ff4d4f' }} />;
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="dashboard-container">
|
||||
<Title level={2}>System Overview</Title>
|
||||
|
||||
{/* System Metrics */}
|
||||
<Row gutter={16} style={{ marginBottom: 24 }}>
|
||||
<Col span={6}>
|
||||
<Card>
|
||||
<Statistic
|
||||
title="CPU Usage"
|
||||
value={systemStats.cpu}
|
||||
suffix="%"
|
||||
prefix={<ServerOutlined />}
|
||||
/>
|
||||
<Progress percent={systemStats.cpu} showInfo={false} />
|
||||
</Card>
|
||||
</Col>
|
||||
<Col span={6}>
|
||||
<Card>
|
||||
<Statistic
|
||||
title="Memory Usage"
|
||||
value={systemStats.memory}
|
||||
suffix="%"
|
||||
prefix={<DatabaseOutlined />}
|
||||
/>
|
||||
<Progress percent={systemStats.memory} showInfo={false} />
|
||||
</Card>
|
||||
</Col>
|
||||
<Col span={6}>
|
||||
<Card>
|
||||
<Statistic
|
||||
title="Disk Usage"
|
||||
value={systemStats.disk}
|
||||
suffix="%"
|
||||
prefix={<DatabaseOutlined />}
|
||||
/>
|
||||
<Progress percent={systemStats.disk} showInfo={false} />
|
||||
</Card>
|
||||
</Col>
|
||||
<Col span={6}>
|
||||
<Card>
|
||||
<Statistic
|
||||
title="Network"
|
||||
value={systemStats.network}
|
||||
suffix="Mbps"
|
||||
prefix={<WifiOutlined />}
|
||||
/>
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Row gutter={16}>
|
||||
{/* Service Status */}
|
||||
<Col span={12}>
|
||||
<Card title="Service Status" style={{ height: 400 }}>
|
||||
<List
|
||||
dataSource={services}
|
||||
renderItem={(service) => (
|
||||
<List.Item>
|
||||
<List.Item.Meta
|
||||
avatar={getStatusIcon(service.status)}
|
||||
title={service.name}
|
||||
description={`Uptime: ${service.uptime}`}
|
||||
/>
|
||||
<Text type={service.status === 'online' ? 'success' : 'danger'}>
|
||||
{service.status.toUpperCase()}
|
||||
</Text>
|
||||
</List.Item>
|
||||
)}
|
||||
/>
|
||||
</Card>
|
||||
</Col>
|
||||
|
||||
{/* Recent Events */}
|
||||
<Col span={12}>
|
||||
<Card title="Recent Events" style={{ height: 400 }}>
|
||||
<List
|
||||
dataSource={recentEvents}
|
||||
renderItem={(event) => (
|
||||
<List.Item>
|
||||
<List.Item.Meta
|
||||
title={event.event}
|
||||
description={`${event.time} • ${event.service}`}
|
||||
/>
|
||||
</List.Item>
|
||||
)}
|
||||
/>
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
{/* System Metrics Chart */}
|
||||
<Row style={{ marginTop: 24 }}>
|
||||
<Col span={24}>
|
||||
<SystemMetrics />
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Dashboard;
|
||||
124
frontend/src/components/Settings.js
Normal file
124
frontend/src/components/Settings.js
Normal file
@@ -0,0 +1,124 @@
|
||||
import React, { useState } from 'react';
|
||||
import { Card, Form, Input, Button, Switch, Select, Divider, Typography, message } from 'antd';
|
||||
|
||||
const { Title, Text } = Typography;
|
||||
const { Option } = Select;
|
||||
|
||||
const Settings = () => {
|
||||
const [form] = Form.useForm();
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const onFinish = (values) => {
|
||||
setLoading(true);
|
||||
// Simulate API call
|
||||
setTimeout(() => {
|
||||
setLoading(false);
|
||||
message.success('Settings saved successfully!');
|
||||
}, 1000);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="dashboard-container">
|
||||
<Title level={2}>Settings</Title>
|
||||
|
||||
<Card title="Service Integrations" style={{ marginBottom: 24 }}>
|
||||
<Form
|
||||
form={form}
|
||||
layout="vertical"
|
||||
onFinish={onFinish}
|
||||
initialValues={{
|
||||
homeAssistant: {
|
||||
enabled: true,
|
||||
url: 'http://homeassistant.local:8123',
|
||||
token: 'your-token-here'
|
||||
},
|
||||
frigate: {
|
||||
enabled: true,
|
||||
url: 'http://frigate.local:5000',
|
||||
token: 'your-token-here'
|
||||
},
|
||||
immich: {
|
||||
enabled: false,
|
||||
url: 'http://immich.local:2283',
|
||||
apiKey: 'your-api-key-here'
|
||||
}
|
||||
}}
|
||||
>
|
||||
{/* Home Assistant */}
|
||||
<Card size="small" title="Home Assistant" style={{ marginBottom: 16 }}>
|
||||
<Form.Item name={['homeAssistant', 'enabled']} valuePropName="checked">
|
||||
<Switch checkedChildren="Enabled" unCheckedChildren="Disabled" />
|
||||
</Form.Item>
|
||||
<Form.Item label="URL" name={['homeAssistant', 'url']}>
|
||||
<Input placeholder="http://homeassistant.local:8123" />
|
||||
</Form.Item>
|
||||
<Form.Item label="Token" name={['homeAssistant', 'token']}>
|
||||
<Input.Password placeholder="Your Home Assistant token" />
|
||||
</Form.Item>
|
||||
</Card>
|
||||
|
||||
{/* Frigate */}
|
||||
<Card size="small" title="Frigate" style={{ marginBottom: 16 }}>
|
||||
<Form.Item name={['frigate', 'enabled']} valuePropName="checked">
|
||||
<Switch checkedChildren="Enabled" unCheckedChildren="Disabled" />
|
||||
</Form.Item>
|
||||
<Form.Item label="URL" name={['frigate', 'url']}>
|
||||
<Input placeholder="http://frigate.local:5000" />
|
||||
</Form.Item>
|
||||
<Form.Item label="Token" name={['frigate', 'token']}>
|
||||
<Input.Password placeholder="Your Frigate token" />
|
||||
</Form.Item>
|
||||
</Card>
|
||||
|
||||
{/* Immich */}
|
||||
<Card size="small" title="Immich" style={{ marginBottom: 16 }}>
|
||||
<Form.Item name={['immich', 'enabled']} valuePropName="checked">
|
||||
<Switch checkedChildren="Enabled" unCheckedChildren="Disabled" />
|
||||
</Form.Item>
|
||||
<Form.Item label="URL" name={['immich', 'url']}>
|
||||
<Input placeholder="http://immich.local:2283" />
|
||||
</Form.Item>
|
||||
<Form.Item label="API Key" name={['immich', 'apiKey']}>
|
||||
<Input.Password placeholder="Your Immich API key" />
|
||||
</Form.Item>
|
||||
</Card>
|
||||
|
||||
<Button type="primary" htmlType="submit" loading={loading}>
|
||||
Save Settings
|
||||
</Button>
|
||||
</Form>
|
||||
</Card>
|
||||
|
||||
<Card title="Dashboard Configuration">
|
||||
<Form layout="vertical">
|
||||
<Form.Item label="Default Dashboard Layout">
|
||||
<Select defaultValue="grid" style={{ width: 200 }}>
|
||||
<Option value="grid">Grid Layout</Option>
|
||||
<Option value="list">List Layout</Option>
|
||||
<Option value="custom">Custom Layout</Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item label="Auto-refresh Interval">
|
||||
<Select defaultValue="30" style={{ width: 200 }}>
|
||||
<Option value="10">10 seconds</Option>
|
||||
<Option value="30">30 seconds</Option>
|
||||
<Option value="60">1 minute</Option>
|
||||
<Option value="300">5 minutes</Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item label="Theme">
|
||||
<Select defaultValue="light" style={{ width: 200 }}>
|
||||
<Option value="light">Light</Option>
|
||||
<Option value="dark">Dark</Option>
|
||||
<Option value="auto">Auto</Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Settings;
|
||||
111
frontend/src/components/SystemMetrics.js
Normal file
111
frontend/src/components/SystemMetrics.js
Normal file
@@ -0,0 +1,111 @@
|
||||
import React from 'react';
|
||||
import { Card, Row, Col, Statistic, Progress } from 'antd';
|
||||
import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, AreaChart, Area } from 'recharts';
|
||||
|
||||
const SystemMetrics = () => {
|
||||
// Mock data for charts
|
||||
const cpuData = [
|
||||
{ time: '00:00', cpu: 25 },
|
||||
{ time: '04:00', cpu: 30 },
|
||||
{ time: '08:00', cpu: 45 },
|
||||
{ time: '12:00', cpu: 60 },
|
||||
{ time: '16:00', cpu: 55 },
|
||||
{ time: '20:00', cpu: 40 },
|
||||
{ time: '24:00', cpu: 35 }
|
||||
];
|
||||
|
||||
const memoryData = [
|
||||
{ time: '00:00', memory: 2.1 },
|
||||
{ time: '04:00', memory: 2.3 },
|
||||
{ time: '08:00', memory: 2.8 },
|
||||
{ time: '12:00', memory: 3.2 },
|
||||
{ time: '16:00', memory: 3.0 },
|
||||
{ time: '20:00', memory: 2.7 },
|
||||
{ time: '24:00', memory: 2.4 }
|
||||
];
|
||||
|
||||
const networkData = [
|
||||
{ time: '00:00', in: 5, out: 3 },
|
||||
{ time: '04:00', in: 8, out: 4 },
|
||||
{ time: '08:00', in: 15, out: 8 },
|
||||
{ time: '12:00', in: 20, out: 12 },
|
||||
{ time: '16:00', in: 18, out: 10 },
|
||||
{ time: '20:00', in: 12, out: 7 },
|
||||
{ time: '24:00', in: 6, out: 4 }
|
||||
];
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Card title="System Performance Metrics" style={{ marginBottom: 16 }}>
|
||||
<Row gutter={16}>
|
||||
<Col span={8}>
|
||||
<Card size="small">
|
||||
<Statistic title="CPU Usage (24h)" value={45.2} suffix="%" />
|
||||
<Progress percent={45.2} showInfo={false} />
|
||||
</Card>
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<Card size="small">
|
||||
<Statistic title="Memory Usage (24h)" value={68.5} suffix="%" />
|
||||
<Progress percent={68.5} showInfo={false} />
|
||||
</Card>
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<Card size="small">
|
||||
<Statistic title="Disk Usage" value={32.1} suffix="%" />
|
||||
<Progress percent={32.1} showInfo={false} />
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
</Card>
|
||||
|
||||
<Row gutter={16}>
|
||||
<Col span={12}>
|
||||
<Card title="CPU Usage Over Time">
|
||||
<ResponsiveContainer width="100%" height={300}>
|
||||
<AreaChart data={cpuData}>
|
||||
<CartesianGrid strokeDasharray="3 3" />
|
||||
<XAxis dataKey="time" />
|
||||
<YAxis />
|
||||
<Tooltip />
|
||||
<Area type="monotone" dataKey="cpu" stroke="#1890ff" fill="#1890ff" fillOpacity={0.3} />
|
||||
</AreaChart>
|
||||
</ResponsiveContainer>
|
||||
</Card>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Card title="Memory Usage Over Time">
|
||||
<ResponsiveContainer width="100%" height={300}>
|
||||
<LineChart data={memoryData}>
|
||||
<CartesianGrid strokeDasharray="3 3" />
|
||||
<XAxis dataKey="time" />
|
||||
<YAxis />
|
||||
<Tooltip />
|
||||
<Line type="monotone" dataKey="memory" stroke="#52c41a" strokeWidth={2} />
|
||||
</LineChart>
|
||||
</ResponsiveContainer>
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Row gutter={16} style={{ marginTop: 16 }}>
|
||||
<Col span={24}>
|
||||
<Card title="Network Traffic">
|
||||
<ResponsiveContainer width="100%" height={300}>
|
||||
<AreaChart data={networkData}>
|
||||
<CartesianGrid strokeDasharray="3 3" />
|
||||
<XAxis dataKey="time" />
|
||||
<YAxis />
|
||||
<Tooltip />
|
||||
<Area type="monotone" dataKey="in" stackId="1" stroke="#1890ff" fill="#1890ff" fillOpacity={0.6} />
|
||||
<Area type="monotone" dataKey="out" stackId="1" stroke="#52c41a" fill="#52c41a" fillOpacity={0.6} />
|
||||
</AreaChart>
|
||||
</ResponsiveContainer>
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SystemMetrics;
|
||||
Reference in New Issue
Block a user