Skip to content
Open
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
111 changes: 73 additions & 38 deletions index.html
Original file line number Diff line number Diff line change
@@ -1,46 +1,81 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=5.0"
/>

<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0" />
<!-- Favicons -->
<link rel="icon" type="image/png" href="/gt-logo-white.png" />
<link rel="apple-touch-icon" href="/gt-logo-white.png" />

<!-- Favicons -->
<link rel="icon" type="image/png" href="/gt-logo-white.png" />
<link rel="apple-touch-icon" href="/gt-logo-white.png" />
<!-- Fonts -->
<link
href="https://fonts.googleapis.com/icon?family=Material+Icons"
rel="stylesheet"
/>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500;600;700&display=swap"
rel="stylesheet"
/>

<!-- Fonts -->
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500;600;700&display=swap"
rel="stylesheet" />
<!-- Primary Meta Tags -->
<title>Gittensor</title>
<meta name="title" content="Gittensor | Autonomous Software Development" />
<meta
name="description"
content="The workforce for open source. Compete for rewards by contributing quality code to open source repositories."
/>

<!-- Primary Meta Tags -->
<title>Gittensor</title>
<meta name="title" content="Gittensor | Autonomous Software Development" />
<meta name="description"
content="The workforce for open source. Compete for rewards by contributing quality code to open source repositories." />
<!-- Open Graph / Facebook -->
<meta property="og:type" content="website" />
<meta
property="og:title"
content="Gittensor | Autonomous Software Development"
/>
<meta
property="og:description"
content="The workforce for open source. Compete for rewards by contributing quality code to open source repositories."
/>
<meta property="og:image" content="/gittensor-og.jpg" />

<!-- Open Graph / Facebook -->
<meta property="og:type" content="website" />
<meta property="og:title" content="Gittensor | Autonomous Software Development" />
<meta property="og:description"
content="The workforce for open source. Compete for rewards by contributing quality code to open source repositories." />
<meta property="og:image" content="/gittensor-og.jpg" />
<!-- X (Twitter) -->
<meta property="twitter:card" content="summary_large_image" />
<meta
property="twitter:title"
content="Gittensor | Autonomous Software Development"
/>
<meta
property="twitter:description"
content="The workforce for open source. Compete for rewards by contributing quality code to open source repositories."
/>
<meta property="twitter:image" content="/gittensor-og.jpg" />
</head>

<!-- X (Twitter) -->
<meta property="twitter:card" content="summary_large_image" />
<meta property="twitter:title" content="Gittensor | Autonomous Software Development" />
<meta property="twitter:description"
content="The workforce for open source. Compete for rewards by contributing quality code to open source repositories." />
<meta property="twitter:image" content="/gittensor-og.jpg" />
</head>

<body style="margin: 0; background-color: #000000">
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>

</html>
<body style="margin: 0">
<!--
Apply the saved theme mode before React mounts so the first paint matches
the user's preference (no white-on-dark or dark-on-white flash). Mirrors
the storage key used by ThemeModeProvider.
-->
<script>
(function () {
try {
var mode = localStorage.getItem('gittensor:theme-mode');
if (mode !== 'light' && mode !== 'dark') mode = 'dark';
document.body.style.backgroundColor =
mode === 'dark' ? '#000000' : '#ffffff';
document.documentElement.dataset.themeMode = mode;
} catch (_) {
document.body.style.backgroundColor = '#000000';
}
})();
</script>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
15 changes: 9 additions & 6 deletions src/components/ContributionHeatmap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Box, Card, Typography, Tooltip, alpha, useTheme } from '@mui/material';
import { ActivityCalendar } from 'react-activity-calendar';
import {
CONTRIBUTION_HEATMAP_SCALE,
CONTRIBUTION_HEATMAP_SCALE_LIGHT,
TEXT_OPACITY,
scrollbarSx,
} from '../theme';
Expand Down Expand Up @@ -39,8 +40,10 @@ const ContributionHeatmap: React.FC<ContributionHeatmapProps> = ({
onDayClick,
}) => {
const theme = useTheme();
const heatmapLevels = [...CONTRIBUTION_HEATMAP_SCALE];
const heatmapTheme = { light: heatmapLevels, dark: heatmapLevels };
const heatmapTheme = {
light: [...CONTRIBUTION_HEATMAP_SCALE_LIGHT],
dark: [...CONTRIBUTION_HEATMAP_SCALE],
};
const isEmpty = data.length === 0;
const interactive = !!onDayClick;

Expand All @@ -60,7 +63,7 @@ const ContributionHeatmap: React.FC<ContributionHeatmapProps> = ({
<Typography
variant="body2"
sx={{
color: alpha(theme.palette.common.white, TEXT_OPACITY.faint),
color: alpha(theme.palette.text.primary, TEXT_OPACITY.faint),
fontSize: '0.85rem',
mt: 0.5,
}}
Expand All @@ -83,7 +86,7 @@ const ContributionHeatmap: React.FC<ContributionHeatmapProps> = ({
>
<Typography
sx={{
color: alpha(theme.palette.common.white, TEXT_OPACITY.muted),
color: alpha(theme.palette.text.primary, TEXT_OPACITY.muted),
fontSize: '0.85rem',
textAlign: 'center',
}}
Expand All @@ -93,7 +96,7 @@ const ContributionHeatmap: React.FC<ContributionHeatmapProps> = ({
{emptySubtitle && (
<Typography
sx={{
color: alpha(theme.palette.common.white, TEXT_OPACITY.ghost),
color: alpha(theme.palette.text.primary, TEXT_OPACITY.ghost),
fontSize: '0.75rem',
textAlign: 'center',
mt: 0.5,
Expand Down Expand Up @@ -182,7 +185,7 @@ const ContributionHeatmap: React.FC<ContributionHeatmapProps> = ({
<Typography
variant="caption"
sx={{
color: alpha(theme.palette.common.white, 0.25),
color: alpha(theme.palette.text.primary, 0.25),
display: 'block',
fontStyle: 'italic',
fontSize: '0.7rem',
Expand Down
21 changes: 12 additions & 9 deletions src/components/DayPRsPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,21 @@ import { Box, Card, Typography, alpha, useTheme } from '@mui/material';
import { format, parseISO } from 'date-fns';
import type { CommitLog } from '../api';
import { LinkBox } from './common/linkBehavior';
import { STATUS_COLORS, TEXT_OPACITY, scrollbarSx } from '../theme';
import { TEXT_OPACITY, scrollbarSx } from '../theme';

interface DayPRsPanelProps {
date: string;
prs: CommitLog[];
username: string;
}

const prStateColor = (pr: CommitLog) => {
if (pr.mergedAt) return STATUS_COLORS.merged;
if (pr.prState === 'CLOSED') return STATUS_COLORS.closed;
return STATUS_COLORS.info;
const prStateColor = (
pr: CommitLog,
palette: { status: { merged: string; closed: string; info: string } },
) => {
if (pr.mergedAt) return palette.status.merged;
if (pr.prState === 'CLOSED') return palette.status.closed;
return palette.status.info;
};

const prStateLabel = (pr: CommitLog) => {
Expand Down Expand Up @@ -66,7 +69,7 @@ const DayPRsPanel: React.FC<DayPRsPanelProps> = ({ date, prs, username }) => {
</Typography>
<Typography
sx={{
color: alpha(theme.palette.common.white, TEXT_OPACITY.faint),
color: alpha(theme.palette.text.primary, TEXT_OPACITY.faint),
fontSize: '0.75rem',
mt: 0.25,
}}
Expand All @@ -79,7 +82,7 @@ const DayPRsPanel: React.FC<DayPRsPanelProps> = ({ date, prs, username }) => {
<Box sx={{ px: 2.5, py: 4, textAlign: 'center' }}>
<Typography
sx={{
color: alpha(theme.palette.common.white, TEXT_OPACITY.muted),
color: alpha(theme.palette.text.primary, TEXT_OPACITY.muted),
fontSize: '0.85rem',
}}
>
Expand All @@ -95,7 +98,7 @@ const DayPRsPanel: React.FC<DayPRsPanelProps> = ({ date, prs, username }) => {
}}
>
{dayPRs.map((pr, idx) => {
const dotColor = prStateColor(pr);
const dotColor = prStateColor(pr, theme.palette);
const stateLabel = prStateLabel(pr);
const detailsHref = `/miners/pr?repo=${encodeURIComponent(pr.repository)}&number=${pr.pullRequestNumber}`;
const timeLabel = pr.mergedAt
Expand Down Expand Up @@ -155,7 +158,7 @@ const DayPRsPanel: React.FC<DayPRsPanelProps> = ({ date, prs, username }) => {
<Typography
sx={{
color: alpha(
theme.palette.common.white,
theme.palette.text.primary,
TEXT_OPACITY.faint,
),
fontSize: '0.7rem',
Expand Down
9 changes: 6 additions & 3 deletions src/components/ErrorFallback.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import React from 'react';
import { Box, Button, Stack, Typography } from '@mui/material';
import { Box, Button, Stack, Typography, useTheme } from '@mui/material';
import ErrorOutlineIcon from '@mui/icons-material/ErrorOutline';
import HomeIcon from '@mui/icons-material/Home';
import RefreshIcon from '@mui/icons-material/Refresh';
import { STATUS_COLORS, scrollbarSx } from '../theme';
import { scrollbarSx } from '../theme';

interface ErrorFallbackProps {
variant: 'fullPage' | 'inline';
Expand All @@ -16,6 +16,7 @@ const ErrorFallback: React.FC<ErrorFallbackProps> = ({
error,
onReset,
}) => {
const theme = useTheme();
const goHome = () => {
window.location.assign('/dashboard');
};
Expand Down Expand Up @@ -50,7 +51,9 @@ const ErrorFallback: React.FC<ErrorFallbackProps> = ({
alignItems="flex-start"
sx={{ maxWidth: 560, width: '100%' }}
>
<ErrorOutlineIcon sx={{ fontSize: 42, color: STATUS_COLORS.closed }} />
<ErrorOutlineIcon
sx={{ fontSize: 42, color: theme.palette.status.closed }}
/>
<Typography
sx={{
fontSize: { xs: '1.25rem', md: '1.5rem' },
Expand Down
17 changes: 11 additions & 6 deletions src/components/FilterButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ interface FilterButtonProps {
isActive: boolean;
onClick: () => void;
count?: number;
color: string;
/** Status color — used as solid active background in light mode */
color?: string;
activeTextColor?: string;
/** When true, button stretches to fill its container (e.g. inside a grid cell). */
fullWidth?: boolean;
Expand All @@ -18,30 +19,34 @@ const FilterButton: React.FC<FilterButtonProps> = ({
onClick,
count,
color,
activeTextColor = 'text.primary',
activeTextColor,
fullWidth = false,
}) => (
<Button
size="small"
onClick={onClick}
fullWidth={fullWidth}
sx={{
color: isActive ? activeTextColor : (t) => t.palette.text.secondary,
sx={(theme) => ({
color: isActive
? (activeTextColor ?? theme.palette.text.primary)
: theme.palette.text.secondary,
backgroundColor: isActive ? 'surface.light' : 'surface.transparent',
borderRadius: '6px',
px: { xs: 1, sm: 1.5 },
py: { xs: 0.5, sm: 0.75 },
minWidth: fullWidth ? 0 : 'auto',
textTransform: 'none',
fontSize: { xs: '0.65rem', sm: '0.75rem' },
fontWeight: isActive ? 600 : 400,
border: isActive ? `1px solid ${color}` : '1px solid transparent',
whiteSpace: 'nowrap',
transition: 'background-color 0.18s ease, color 0.18s ease',
'&:hover': {
backgroundColor: 'border.light',
},
}}
})}
>
{label}{' '}
{label}
{count !== undefined && (
<Box
component="span"
Expand Down
5 changes: 1 addition & 4 deletions src/components/KpiCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
useMediaQuery,
useTheme,
} from '@mui/material';
import theme from '../theme';

interface KpiCardProps {
title: string;
Expand All @@ -26,7 +25,7 @@ const KpiCard: React.FC<KpiCardProps> = ({
sx,
}) => {
const muiTheme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
const isMobile = useMediaQuery(muiTheme.breakpoints.down('sm'));
const isLarge = variant === 'large';
const padding = isLarge
? { py: isMobile ? 1.6 : 2 }
Expand All @@ -48,8 +47,6 @@ const KpiCard: React.FC<KpiCardProps> = ({
<Card
sx={{
borderRadius: 3,
border: `1px solid ${muiTheme.palette.border.light}`,
backgroundColor: 'transparent',
height: '100%',
...sx,
}}
Expand Down
4 changes: 2 additions & 2 deletions src/components/common/WatchlistButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,12 @@ export const WatchlistButton: React.FC<WatchlistButtonProps> = ({
aria-label={label}
aria-pressed={watched}
sx={{
color: watched ? 'warning.main' : 'text.tertiary',
color: watched ? 'status.award' : 'text.tertiary',
transition: 'color 0.15s, transform 0.15s',
'&:hover': {
color: 'warning.light',
transform: 'scale(1.08)',
backgroundColor: 'rgba(255,255,255,0.06)',
backgroundColor: 'border.subtle',
},
...sx,
}}
Expand Down
Loading
Loading