Skip to content
Draft
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
7,528 changes: 3,764 additions & 3,764 deletions package-lock.json

Large diffs are not rendered by default.

17 changes: 16 additions & 1 deletion src/app.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
import * as React from "react";
import ReactDOM from "react-dom";
import { ThemeProvider } from "@material-ui/core/styles";
import CssBaseline from "@material-ui/core/CssBaseline";
import Routes from "./route";
import theme from "./theme";

ReactDOM.render(<Routes />, document.getElementById("app"));
// Add Inter font
const link = document.createElement('link');
link.href = 'https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap';
link.rel = 'stylesheet';
document.head.appendChild(link);

ReactDOM.render(
<ThemeProvider theme={theme}>
<CssBaseline />
<Routes />
</ThemeProvider>,
document.getElementById("app")
);
200 changes: 200 additions & 0 deletions src/components/DashboardWelcome.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
import React from 'react';
import {
Box,
Typography,
Card,
CardContent,
Grid,
Chip,
useTheme
} from '@material-ui/core';
import { makeStyles } from '@material-ui/styles';
import {
TrendingUp,
Assessment,
CloudQueue,
AttachMoney,
Speed,
Security
} from '@material-ui/icons';

const useStyles = makeStyles((theme) => ({
welcomeContainer: {
marginBottom: '32px',
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
borderRadius: '20px',
padding: '40px',
color: 'white',
position: 'relative',
overflow: 'hidden',
'&:before': {
content: '""',
position: 'absolute',
top: '-50%',
right: '-20%',
width: '300px',
height: '300px',
background: 'rgba(255, 255, 255, 0.1)',
borderRadius: '50%',
filter: 'blur(60px)',
},
},
welcomeContent: {
position: 'relative',
zIndex: 1,
},
welcomeTitle: {
fontSize: '2.5rem',
fontWeight: 700,
marginBottom: '12px',
letterSpacing: '-0.025em',
},
welcomeSubtitle: {
fontSize: '1.25rem',
opacity: 0.9,
marginBottom: '24px',
},
statsContainer: {
marginTop: '24px',
},
statCard: {
background: 'rgba(255, 255, 255, 0.95)',
backdropFilter: 'blur(10px)',
borderRadius: '16px',
padding: '24px',
height: '100%',
border: '1px solid rgba(255, 255, 255, 0.2)',
transition: 'transform 0.2s ease, box-shadow 0.2s ease',
'&:hover': {
transform: 'translateY(-4px)',
boxShadow: '0 20px 40px rgba(0, 0, 0, 0.1)',
},
},
statIcon: {
width: '48px',
height: '48px',
borderRadius: '12px',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
marginBottom: '16px',
background: 'linear-gradient(135deg, #2563eb 0%, #3b82f6 100%)',
color: 'white',
},
statTitle: {
fontSize: '0.875rem',
fontWeight: 600,
color: theme.palette.text.secondary,
textTransform: 'uppercase',
letterSpacing: '0.05em',
marginBottom: '8px',
},
statValue: {
fontSize: '1.875rem',
fontWeight: 700,
color: theme.palette.text.primary,
marginBottom: '4px',
},
statDescription: {
fontSize: '0.875rem',
color: theme.palette.text.secondary,
},
featureChip: {
backgroundColor: 'rgba(255, 255, 255, 0.2)',
color: 'white',
margin: '4px',
fontWeight: 500,
},
}));

const DashboardWelcome = () => {
const classes = useStyles();
const theme = useTheme();

const features = [
'Real-time Monitoring',
'Cost Optimization',
'Multi-cloud Support',
'Custom Reports',
'Advanced Analytics'
];

const stats = [
{
icon: <TrendingUp />,
title: 'Cost Tracking',
value: 'Active',
description: 'Real-time cost monitoring'
},
{
icon: <Assessment />,
title: 'Analytics',
value: 'Ready',
description: 'Advanced cost analytics'
},
{
icon: <CloudQueue />,
title: 'Cloud Support',
value: 'Multi',
description: 'AWS, GCP, Azure compatible'
},
{
icon: <Speed />,
title: 'Performance',
value: 'Optimized',
description: 'High-speed data processing'
}
];

return (
<Box className={`${classes.welcomeContainer} fade-in`}>
<div className={classes.welcomeContent}>
<Typography className={classes.welcomeTitle}>
Welcome to OpenCost
</Typography>
<Typography className={classes.welcomeSubtitle}>
Your comprehensive cloud cost management and monitoring platform
</Typography>

<Box display="flex" flexWrap="wrap" mt={2}>
{features.map((feature) => (
<Chip
key={feature}
label={feature}
className={classes.featureChip}
size="small"
/>
))}
</Box>

<Grid container spacing={3} className={classes.statsContainer}>
{stats.map((stat, index) => (
<Grid item xs={12} sm={6} md={3} key={stat.title}>
<Card
className={`${classes.statCard} hover-lift`}
style={{ animationDelay: `${index * 100}ms` }}
>
<CardContent style={{ padding: '0', paddingBottom: '0 !important' }}>
<div className={classes.statIcon}>
{stat.icon}
</div>
<Typography className={classes.statTitle}>
{stat.title}
</Typography>
<Typography className={classes.statValue}>
{stat.value}
</Typography>
<Typography className={classes.statDescription}>
{stat.description}
</Typography>
</CardContent>
</Card>
</Grid>
))}
</Grid>
</div>
</Box>
);
};

export default DashboardWelcome;
159 changes: 151 additions & 8 deletions src/components/Footer.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,156 @@
import {Parser as HtmlToReactParser} from 'html-to-react'
import React from 'react';
import { Typography, Box, Container, Grid, Link, Divider } from '@material-ui/core';
import { makeStyles } from '@material-ui/styles';
import { GitHub, Language, Book } from '@material-ui/icons';

const useStyles = makeStyles((theme) => ({
footer: {
background: 'linear-gradient(135deg, #1e293b 0%, #334155 100%)',
color: 'white',
marginTop: 'auto',
padding: '48px 0 32px',
position: 'relative',
overflow: 'hidden',
'&:before': {
content: '""',
position: 'absolute',
top: 0,
left: 0,
right: 0,
height: '4px',
background: 'linear-gradient(90deg, #2563eb 0%, #10b981 100%)',
},
},
container: {
position: 'relative',
zIndex: 1,
},
logo: {
fontSize: '1.5rem',
fontWeight: 700,
marginBottom: '12px',
background: 'linear-gradient(135deg, #60a5fa 0%, #34d399 100%)',
backgroundClip: 'text',
WebkitBackgroundClip: 'text',
WebkitTextFillColor: 'transparent',
},
description: {
color: 'rgba(255, 255, 255, 0.8)',
marginBottom: '24px',
lineHeight: 1.6,
},
sectionTitle: {
fontSize: '1.125rem',
fontWeight: 600,
marginBottom: '16px',
color: 'white',
},
link: {
color: 'rgba(255, 255, 255, 0.8)',
textDecoration: 'none',
display: 'flex',
alignItems: 'center',
padding: '8px 0',
transition: 'color 0.2s ease',
'&:hover': {
color: '#60a5fa',
},
},
linkIcon: {
marginRight: '8px',
fontSize: '1.125rem',
},
copyright: {
textAlign: 'center',
color: 'rgba(255, 255, 255, 0.6)',
fontSize: '0.875rem',
marginTop: '32px',
paddingTop: '24px',
borderTop: '1px solid rgba(255, 255, 255, 0.1)',
},
decorativeElement: {
position: 'absolute',
bottom: '-100px',
right: '-100px',
width: '200px',
height: '200px',
background: 'linear-gradient(135deg, rgba(37, 99, 235, 0.1) 0%, rgba(16, 185, 129, 0.1) 100%)',
borderRadius: '50%',
filter: 'blur(40px)',
},
}));

// Footer could be HTML, so we need to parse it.
const Footer = () => {
const content = '<div align="right"><br/>PLACEHOLDER_FOOTER_CONTENT</div>';
const htmlToReactParser = new HtmlToReactParser();
const parsedContent = htmlToReactParser.parse(content);
const classes = useStyles();

return (
parsedContent
)
}
<footer className={classes.footer}>
<div className={classes.decorativeElement} />
<Container maxWidth="lg" className={classes.container}>
<Grid container spacing={4}>
<Grid item xs={12} md={4}>
<Typography className={classes.logo}>
OpenCost
</Typography>
<Typography className={classes.description}>
Open source cost management and monitoring for cloud infrastructure.
Get real-time insights into your Kubernetes and cloud costs.
</Typography>
</Grid>

<Grid item xs={12} md={4}>
<Typography className={classes.sectionTitle}>
Resources
</Typography>
<Link
href="https://opencost.io"
target="_blank"
rel="noopener noreferrer"
className={classes.link}
>
<Language className={classes.linkIcon} />
Official Website
</Link>
<Link
href="https://docs.opencost.io"
target="_blank"
rel="noopener noreferrer"
className={classes.link}
>
<Book className={classes.linkIcon} />
Documentation
</Link>
<Link
href="https://github.com/opencost/opencost"
target="_blank"
rel="noopener noreferrer"
className={classes.link}
>
<GitHub className={classes.linkIcon} />
GitHub Repository
</Link>
</Grid>

<Grid item xs={12} md={4}>
<Typography className={classes.sectionTitle}>
Features
</Typography>
<Typography className={classes.description}>
• Real-time cost allocation<br />
• Multi-cloud support<br />
• Kubernetes native<br />
• Custom reporting<br />
• Cost optimization insights
</Typography>
</Grid>
</Grid>

<Typography className={classes.copyright}>
© {new Date().getFullYear()} OpenCost - Open Source Cost Management Platform
</Typography>
</Container>
</footer>
);
};

export default Footer;
Loading