mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-14 20:41:09 +02:00
✨ feat(devlog): add activity grid page and extended stats
Add GitHub-style activity grid showing development contributions: - Activity grid with color-coded commit intensity - Total stats: commits, files changed, lines added/removed - Contributors section with commit counts - Recent activity list Extended devlog schema with: - stats: filesChanged, linesAdded, linesRemoved - contributors: name, handle, commits per contributor - workingHours: start/end timestamps Updated all 9 devlogs with accurate git stats. Added link to activity page from devlog index.
This commit is contained in:
parent
210969a67f
commit
f4c2663122
13 changed files with 496 additions and 2 deletions
|
|
@ -154,6 +154,30 @@ const devlogCollection = defineCollection({
|
||||||
featured: z.boolean().default(false),
|
featured: z.boolean().default(false),
|
||||||
commits: z.number().optional(),
|
commits: z.number().optional(),
|
||||||
readTime: z.number().optional(),
|
readTime: z.number().optional(),
|
||||||
|
// Extended stats for activity grid
|
||||||
|
stats: z
|
||||||
|
.object({
|
||||||
|
filesChanged: z.number(),
|
||||||
|
linesAdded: z.number(),
|
||||||
|
linesRemoved: z.number(),
|
||||||
|
})
|
||||||
|
.optional(),
|
||||||
|
contributors: z
|
||||||
|
.array(
|
||||||
|
z.object({
|
||||||
|
name: z.string(),
|
||||||
|
handle: z.string().optional(),
|
||||||
|
commits: z.number().optional(),
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.optional(),
|
||||||
|
// Working hours (11:00 to 11:00 next day convention)
|
||||||
|
workingHours: z
|
||||||
|
.object({
|
||||||
|
start: z.string(), // e.g., "2026-01-30T11:00"
|
||||||
|
end: z.string(), // e.g., "2026-01-31T11:00"
|
||||||
|
})
|
||||||
|
.optional(),
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,17 @@ tags:
|
||||||
featured: true
|
featured: true
|
||||||
commits: 43
|
commits: 43
|
||||||
readTime: 12
|
readTime: 12
|
||||||
|
stats:
|
||||||
|
filesChanged: 222
|
||||||
|
linesAdded: 19273
|
||||||
|
linesRemoved: 985
|
||||||
|
contributors:
|
||||||
|
- name: 'Till Schneider'
|
||||||
|
handle: 'Till-JS'
|
||||||
|
commits: 43
|
||||||
|
workingHours:
|
||||||
|
start: '2026-01-23T11:00'
|
||||||
|
end: '2026-01-24T11:00'
|
||||||
---
|
---
|
||||||
|
|
||||||
Heute war ein sehr produktiver Tag mit Fokus auf die **Produktivstellung der ManaCore Apps auf dem Mac Mini Server**. Die wichtigsten Errungenschaften:
|
Heute war ein sehr produktiver Tag mit Fokus auf die **Produktivstellung der ManaCore Apps auf dem Mac Mini Server**. Die wichtigsten Errungenschaften:
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,17 @@ tags:
|
||||||
featured: true
|
featured: true
|
||||||
commits: 54
|
commits: 54
|
||||||
readTime: 10
|
readTime: 10
|
||||||
|
stats:
|
||||||
|
filesChanged: 155
|
||||||
|
linesAdded: 11566
|
||||||
|
linesRemoved: 2290
|
||||||
|
contributors:
|
||||||
|
- name: 'Till Schneider'
|
||||||
|
handle: 'Till-JS'
|
||||||
|
commits: 54
|
||||||
|
workingHours:
|
||||||
|
start: '2026-01-26T11:00'
|
||||||
|
end: '2026-01-27T11:00'
|
||||||
---
|
---
|
||||||
|
|
||||||
Produktiver Tag mit Fokus auf **Monitoring-Infrastruktur**, **Email-Authentifizierung** und **lokale AI-Services**. Die wichtigsten Errungenschaften:
|
Produktiver Tag mit Fokus auf **Monitoring-Infrastruktur**, **Email-Authentifizierung** und **lokale AI-Services**. Die wichtigsten Errungenschaften:
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,17 @@ tags:
|
||||||
featured: true
|
featured: true
|
||||||
commits: 74
|
commits: 74
|
||||||
readTime: 20
|
readTime: 20
|
||||||
|
stats:
|
||||||
|
filesChanged: 747
|
||||||
|
linesAdded: 56325
|
||||||
|
linesRemoved: 11567
|
||||||
|
contributors:
|
||||||
|
- name: 'Till Schneider'
|
||||||
|
handle: 'Till-JS'
|
||||||
|
commits: 74
|
||||||
|
workingHours:
|
||||||
|
start: '2026-01-28T11:00'
|
||||||
|
end: '2026-01-29T11:00'
|
||||||
---
|
---
|
||||||
|
|
||||||
Außergewöhnlich produktiver Tag (und Nacht!) mit **74 Commits** und mehreren großen neuen Features. Die wichtigsten Errungenschaften:
|
Außergewöhnlich produktiver Tag (und Nacht!) mit **74 Commits** und mehreren großen neuen Features. Die wichtigsten Errungenschaften:
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,17 @@ tags:
|
||||||
featured: true
|
featured: true
|
||||||
commits: 55
|
commits: 55
|
||||||
readTime: 25
|
readTime: 25
|
||||||
|
stats:
|
||||||
|
filesChanged: 1082
|
||||||
|
linesAdded: 51520
|
||||||
|
linesRemoved: 12296
|
||||||
|
contributors:
|
||||||
|
- name: 'Till Schneider'
|
||||||
|
handle: 'Till-JS'
|
||||||
|
commits: 55
|
||||||
|
workingHours:
|
||||||
|
start: '2026-01-29T11:00'
|
||||||
|
end: '2026-01-30T11:00'
|
||||||
---
|
---
|
||||||
|
|
||||||
Außergewöhnlich produktiver Tag mit **55 Commits** - aufgeteilt in drei große Bereiche:
|
Außergewöhnlich produktiver Tag mit **55 Commits** - aufgeteilt in drei große Bereiche:
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,17 @@ tags:
|
||||||
featured: false
|
featured: false
|
||||||
commits: 41
|
commits: 41
|
||||||
readTime: 12
|
readTime: 12
|
||||||
|
stats:
|
||||||
|
filesChanged: 289
|
||||||
|
linesAdded: 17857
|
||||||
|
linesRemoved: 2113
|
||||||
|
contributors:
|
||||||
|
- name: 'Till Schneider'
|
||||||
|
handle: 'Till-JS'
|
||||||
|
commits: 41
|
||||||
|
workingHours:
|
||||||
|
start: '2026-01-30T11:00'
|
||||||
|
end: '2026-01-31T11:00'
|
||||||
---
|
---
|
||||||
|
|
||||||
Produktiver Tag mit **41 Commits** und Fokus auf Matrix Bot Expansion und Developer Experience:
|
Produktiver Tag mit **41 Commits** und Fokus auf Matrix Bot Expansion und Developer Experience:
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,17 @@ tags:
|
||||||
featured: true
|
featured: true
|
||||||
commits: 52
|
commits: 52
|
||||||
readTime: 18
|
readTime: 18
|
||||||
|
stats:
|
||||||
|
filesChanged: 570
|
||||||
|
linesAdded: 24147
|
||||||
|
linesRemoved: 19564
|
||||||
|
contributors:
|
||||||
|
- name: 'Till Schneider'
|
||||||
|
handle: 'Till-JS'
|
||||||
|
commits: 52
|
||||||
|
workingHours:
|
||||||
|
start: '2026-01-31T11:00'
|
||||||
|
end: '2026-02-01T11:00'
|
||||||
---
|
---
|
||||||
|
|
||||||
Intensiver Tag (und Nacht!) mit **52 Commits** - der Fokus lag auf der Konsolidierung der Matrix Bot Infrastruktur:
|
Intensiver Tag (und Nacht!) mit **52 Commits** - der Fokus lag auf der Konsolidierung der Matrix Bot Infrastruktur:
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,17 @@ tags:
|
||||||
featured: false
|
featured: false
|
||||||
commits: 42
|
commits: 42
|
||||||
readTime: 14
|
readTime: 14
|
||||||
|
stats:
|
||||||
|
filesChanged: 289
|
||||||
|
linesAdded: 14561
|
||||||
|
linesRemoved: 3780
|
||||||
|
contributors:
|
||||||
|
- name: 'Till Schneider'
|
||||||
|
handle: 'Till-JS'
|
||||||
|
commits: 42
|
||||||
|
workingHours:
|
||||||
|
start: '2026-02-01T11:00'
|
||||||
|
end: '2026-02-02T11:00'
|
||||||
---
|
---
|
||||||
|
|
||||||
Produktiver Tag mit **42 Commits** und Fokus auf Infrastructure und Production Readiness:
|
Produktiver Tag mit **42 Commits** und Fokus auf Infrastructure und Production Readiness:
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,17 @@ tags:
|
||||||
featured: true
|
featured: true
|
||||||
commits: 40
|
commits: 40
|
||||||
readTime: 15
|
readTime: 15
|
||||||
|
stats:
|
||||||
|
filesChanged: 207
|
||||||
|
linesAdded: 9495
|
||||||
|
linesRemoved: 6405
|
||||||
|
contributors:
|
||||||
|
- name: 'Till Schneider'
|
||||||
|
handle: 'Till-JS'
|
||||||
|
commits: 40
|
||||||
|
workingHours:
|
||||||
|
start: '2026-02-02T11:00'
|
||||||
|
end: '2026-02-03T11:00'
|
||||||
---
|
---
|
||||||
|
|
||||||
Produktiver Tag mit **40 Commits** und Fokus auf nahtlose Authentifizierung über alle Apps:
|
Produktiver Tag mit **40 Commits** und Fokus auf nahtlose Authentifizierung über alle Apps:
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,17 @@ tags:
|
||||||
featured: true
|
featured: true
|
||||||
commits: 28
|
commits: 28
|
||||||
readTime: 14
|
readTime: 14
|
||||||
|
stats:
|
||||||
|
filesChanged: 241
|
||||||
|
linesAdded: 14772
|
||||||
|
linesRemoved: 1668
|
||||||
|
contributors:
|
||||||
|
- name: 'Till Schneider'
|
||||||
|
handle: 'Till-JS'
|
||||||
|
commits: 28
|
||||||
|
workingHours:
|
||||||
|
start: '2026-02-11T11:00'
|
||||||
|
end: '2026-02-12T11:00'
|
||||||
---
|
---
|
||||||
|
|
||||||
Nach einer Woche Pause: **28 Commits** mit Fokus auf neue Apps und API-Infrastruktur:
|
Nach einer Woche Pause: **28 Commits** mit Fokus auf neue Apps und API-Infrastruktur:
|
||||||
|
|
|
||||||
322
apps/manacore/apps/landing/src/pages/devlog/activity.astro
Normal file
322
apps/manacore/apps/landing/src/pages/devlog/activity.astro
Normal file
|
|
@ -0,0 +1,322 @@
|
||||||
|
---
|
||||||
|
import Layout from '../../layouts/Layout.astro';
|
||||||
|
import Navbar from '../../components/navigation/Navbar.astro';
|
||||||
|
import Footer from '../../components/navigation/Footer.astro';
|
||||||
|
import Section from '../../components/content/Section.astro';
|
||||||
|
import Container from '../../components/layout/Container.astro';
|
||||||
|
import Heading from '../../components/typography/Heading.astro';
|
||||||
|
import Text from '../../components/typography/Text.astro';
|
||||||
|
import HeroSection from '../../components/content/HeroSection.astro';
|
||||||
|
import { getCollection } from 'astro:content';
|
||||||
|
import { Icon } from 'astro-icon/components';
|
||||||
|
|
||||||
|
const posts = await getCollection('devlog');
|
||||||
|
const sortedPosts = posts.sort((a, b) => a.data.date.getTime() - b.data.date.getTime());
|
||||||
|
|
||||||
|
// Generate activity data for the grid (last 365 days)
|
||||||
|
const today = new Date();
|
||||||
|
const startDate = new Date(today);
|
||||||
|
startDate.setDate(startDate.getDate() - 364);
|
||||||
|
|
||||||
|
// Create a map of date -> activity level
|
||||||
|
const activityMap = new Map<string, { commits: number; linesAdded: number; linesRemoved: number; posts: string[] }>();
|
||||||
|
|
||||||
|
for (const post of sortedPosts) {
|
||||||
|
const dateKey = post.data.date.toISOString().split('T')[0];
|
||||||
|
const existing = activityMap.get(dateKey) || { commits: 0, linesAdded: 0, linesRemoved: 0, posts: [] };
|
||||||
|
activityMap.set(dateKey, {
|
||||||
|
commits: existing.commits + (post.data.commits || 0),
|
||||||
|
linesAdded: existing.linesAdded + (post.data.stats?.linesAdded || 0),
|
||||||
|
linesRemoved: existing.linesRemoved + (post.data.stats?.linesRemoved || 0),
|
||||||
|
posts: [...existing.posts, post.data.title],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate weeks for the grid
|
||||||
|
const weeks: { date: Date; dateKey: string; activity: number; commits: number; posts: string[] }[][] = [];
|
||||||
|
let currentWeek: { date: Date; dateKey: string; activity: number; commits: number; posts: string[] }[] = [];
|
||||||
|
const currentDate = new Date(startDate);
|
||||||
|
|
||||||
|
// Pad the first week to start on Sunday
|
||||||
|
const firstDayOfWeek = currentDate.getDay();
|
||||||
|
for (let i = 0; i < firstDayOfWeek; i++) {
|
||||||
|
currentWeek.push({ date: new Date(0), dateKey: '', activity: -1, commits: 0, posts: [] });
|
||||||
|
}
|
||||||
|
|
||||||
|
while (currentDate <= today) {
|
||||||
|
const dateKey = currentDate.toISOString().split('T')[0];
|
||||||
|
const data = activityMap.get(dateKey);
|
||||||
|
const commits = data?.commits || 0;
|
||||||
|
|
||||||
|
// Activity level: 0 = none, 1 = low, 2 = medium, 3 = high, 4 = very high
|
||||||
|
let activity = 0;
|
||||||
|
if (commits > 0) activity = 1;
|
||||||
|
if (commits >= 20) activity = 2;
|
||||||
|
if (commits >= 40) activity = 3;
|
||||||
|
if (commits >= 60) activity = 4;
|
||||||
|
|
||||||
|
currentWeek.push({
|
||||||
|
date: new Date(currentDate),
|
||||||
|
dateKey,
|
||||||
|
activity,
|
||||||
|
commits,
|
||||||
|
posts: data?.posts || [],
|
||||||
|
});
|
||||||
|
|
||||||
|
if (currentWeek.length === 7) {
|
||||||
|
weeks.push(currentWeek);
|
||||||
|
currentWeek = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
currentDate.setDate(currentDate.getDate() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Push remaining days
|
||||||
|
if (currentWeek.length > 0) {
|
||||||
|
weeks.push(currentWeek);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate totals
|
||||||
|
const totalCommits = sortedPosts.reduce((sum, post) => sum + (post.data.commits || 0), 0);
|
||||||
|
const totalLinesAdded = sortedPosts.reduce((sum, post) => sum + (post.data.stats?.linesAdded || 0), 0);
|
||||||
|
const totalLinesRemoved = sortedPosts.reduce((sum, post) => sum + (post.data.stats?.linesRemoved || 0), 0);
|
||||||
|
const totalFilesChanged = sortedPosts.reduce((sum, post) => sum + (post.data.stats?.filesChanged || 0), 0);
|
||||||
|
const totalDays = sortedPosts.length;
|
||||||
|
|
||||||
|
// Get all contributors
|
||||||
|
const contributorMap = new Map<string, { name: string; handle?: string; commits: number }>();
|
||||||
|
for (const post of sortedPosts) {
|
||||||
|
for (const contributor of post.data.contributors || []) {
|
||||||
|
const existing = contributorMap.get(contributor.name) || { name: contributor.name, handle: contributor.handle, commits: 0 };
|
||||||
|
contributorMap.set(contributor.name, {
|
||||||
|
...existing,
|
||||||
|
commits: existing.commits + (contributor.commits || 0),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const contributors = Array.from(contributorMap.values()).sort((a, b) => b.commits - a.commits);
|
||||||
|
|
||||||
|
const activityColors = [
|
||||||
|
'bg-gray-100 dark:bg-gray-800', // 0 - none
|
||||||
|
'bg-green-200 dark:bg-green-900', // 1 - low
|
||||||
|
'bg-green-400 dark:bg-green-700', // 2 - medium
|
||||||
|
'bg-green-500 dark:bg-green-600', // 3 - high
|
||||||
|
'bg-green-600 dark:bg-green-500', // 4 - very high
|
||||||
|
];
|
||||||
|
|
||||||
|
const monthLabels = ['Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'];
|
||||||
|
const dayLabels = ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa'];
|
||||||
|
|
||||||
|
const formatNumber = (num: number) => {
|
||||||
|
if (num >= 1000000) return (num / 1000000).toFixed(1) + 'M';
|
||||||
|
if (num >= 1000) return (num / 1000).toFixed(1) + 'K';
|
||||||
|
return num.toString();
|
||||||
|
};
|
||||||
|
|
||||||
|
const formatDate = (date: Date) => {
|
||||||
|
return new Intl.DateTimeFormat('de-DE', {
|
||||||
|
day: '2-digit',
|
||||||
|
month: 'long',
|
||||||
|
year: 'numeric',
|
||||||
|
}).format(date);
|
||||||
|
};
|
||||||
|
---
|
||||||
|
|
||||||
|
<Layout title="Aktivität - ManaCore Entwicklung">
|
||||||
|
<div class="bg-gradient-to-b from-blue-50/30 via-white to-blue-50/30 dark:from-gray-900 dark:via-gray-900 dark:to-gray-900">
|
||||||
|
<Navbar />
|
||||||
|
|
||||||
|
<!-- Hero Section -->
|
||||||
|
<div class="relative">
|
||||||
|
<div class="absolute inset-0 -bottom-32">
|
||||||
|
<div class="absolute inset-0 bg-gradient-to-b from-blue-50/50 to-transparent dark:from-gray-900 dark:to-transparent"></div>
|
||||||
|
<div class="absolute top-0 right-0 w-96 h-96 bg-green-500/10 dark:bg-green-500/5 rounded-full blur-3xl"></div>
|
||||||
|
<div class="absolute bottom-0 left-0 w-96 h-96 bg-emerald-500/10 dark:bg-emerald-500/5 rounded-full blur-3xl"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<HeroSection
|
||||||
|
title="Entwicklungsaktivität"
|
||||||
|
subtitle="Übersicht der Entwicklungsarbeit am ManaCore Projekt. Jeder Tag zählt."
|
||||||
|
background="none"
|
||||||
|
minHeight="small"
|
||||||
|
spacing="small"
|
||||||
|
containerClass="py-16 relative z-10"
|
||||||
|
centered={true}
|
||||||
|
debug={false}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Stats Cards -->
|
||||||
|
<Section spacing="medium" class="relative">
|
||||||
|
<Container>
|
||||||
|
<div class="grid grid-cols-2 md:grid-cols-4 gap-4 mb-12">
|
||||||
|
<div class="bg-white/90 dark:bg-gray-800/90 backdrop-blur-sm rounded-xl p-6 border border-gray-200 dark:border-gray-700">
|
||||||
|
<div class="flex items-center gap-3 mb-2">
|
||||||
|
<div class="w-10 h-10 rounded-lg bg-gradient-to-br from-green-500/20 to-emerald-500/20 flex items-center justify-center">
|
||||||
|
<Icon name="mdi:source-commit" class="w-5 h-5 text-green-600 dark:text-green-400" />
|
||||||
|
</div>
|
||||||
|
<Text size="sm" class="text-gray-500 dark:text-gray-400">Commits</Text>
|
||||||
|
</div>
|
||||||
|
<Heading as="h3" size="3" class="text-green-600 dark:text-green-400">{totalCommits}</Heading>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="bg-white/90 dark:bg-gray-800/90 backdrop-blur-sm rounded-xl p-6 border border-gray-200 dark:border-gray-700">
|
||||||
|
<div class="flex items-center gap-3 mb-2">
|
||||||
|
<div class="w-10 h-10 rounded-lg bg-gradient-to-br from-blue-500/20 to-cyan-500/20 flex items-center justify-center">
|
||||||
|
<Icon name="mdi:file-document-outline" class="w-5 h-5 text-blue-600 dark:text-blue-400" />
|
||||||
|
</div>
|
||||||
|
<Text size="sm" class="text-gray-500 dark:text-gray-400">Dateien</Text>
|
||||||
|
</div>
|
||||||
|
<Heading as="h3" size="3" class="text-blue-600 dark:text-blue-400">{formatNumber(totalFilesChanged)}</Heading>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="bg-white/90 dark:bg-gray-800/90 backdrop-blur-sm rounded-xl p-6 border border-gray-200 dark:border-gray-700">
|
||||||
|
<div class="flex items-center gap-3 mb-2">
|
||||||
|
<div class="w-10 h-10 rounded-lg bg-gradient-to-br from-emerald-500/20 to-green-500/20 flex items-center justify-center">
|
||||||
|
<Icon name="mdi:plus" class="w-5 h-5 text-emerald-600 dark:text-emerald-400" />
|
||||||
|
</div>
|
||||||
|
<Text size="sm" class="text-gray-500 dark:text-gray-400">Zeilen +</Text>
|
||||||
|
</div>
|
||||||
|
<Heading as="h3" size="3" class="text-emerald-600 dark:text-emerald-400">+{formatNumber(totalLinesAdded)}</Heading>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="bg-white/90 dark:bg-gray-800/90 backdrop-blur-sm rounded-xl p-6 border border-gray-200 dark:border-gray-700">
|
||||||
|
<div class="flex items-center gap-3 mb-2">
|
||||||
|
<div class="w-10 h-10 rounded-lg bg-gradient-to-br from-red-500/20 to-orange-500/20 flex items-center justify-center">
|
||||||
|
<Icon name="mdi:minus" class="w-5 h-5 text-red-600 dark:text-red-400" />
|
||||||
|
</div>
|
||||||
|
<Text size="sm" class="text-gray-500 dark:text-gray-400">Zeilen -</Text>
|
||||||
|
</div>
|
||||||
|
<Heading as="h3" size="3" class="text-red-600 dark:text-red-400">-{formatNumber(totalLinesRemoved)}</Heading>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Activity Grid -->
|
||||||
|
<div class="bg-white/90 dark:bg-gray-800/90 backdrop-blur-sm rounded-2xl p-6 border border-gray-200 dark:border-gray-700 mb-8">
|
||||||
|
<div class="flex items-center justify-between mb-6">
|
||||||
|
<Heading as="h2" size="4">{totalDays} aktive Entwicklungstage</Heading>
|
||||||
|
<a href="/devlog" class="text-sm text-mana-blue hover:underline flex items-center gap-1">
|
||||||
|
Alle Devlogs
|
||||||
|
<Icon name="mdi:arrow-right" class="w-4 h-4" />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Grid -->
|
||||||
|
<div class="overflow-x-auto">
|
||||||
|
<div class="inline-flex gap-1">
|
||||||
|
<!-- Day labels -->
|
||||||
|
<div class="flex flex-col gap-1 mr-2 text-xs text-gray-400">
|
||||||
|
{dayLabels.map((day, i) => (
|
||||||
|
<div class="h-3 flex items-center" style={i % 2 === 0 ? '' : 'visibility: hidden'}>
|
||||||
|
{day}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Weeks -->
|
||||||
|
{weeks.map((week, weekIndex) => (
|
||||||
|
<div class="flex flex-col gap-1">
|
||||||
|
{week.map((day) => (
|
||||||
|
<div
|
||||||
|
class={`w-3 h-3 rounded-sm ${day.activity === -1 ? 'bg-transparent' : activityColors[day.activity]} ${day.commits > 0 ? 'cursor-pointer hover:ring-2 hover:ring-offset-1 hover:ring-green-500' : ''}`}
|
||||||
|
title={day.activity === -1 ? '' : `${formatDate(day.date)}: ${day.commits} Commits${day.posts.length > 0 ? '\n' + day.posts.join(', ') : ''}`}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Legend -->
|
||||||
|
<div class="flex items-center justify-end gap-2 mt-4 text-xs text-gray-500">
|
||||||
|
<span>Weniger</span>
|
||||||
|
{activityColors.map((color) => (
|
||||||
|
<div class={`w-3 h-3 rounded-sm ${color}`} />
|
||||||
|
))}
|
||||||
|
<span>Mehr</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Contributors -->
|
||||||
|
<div class="bg-white/90 dark:bg-gray-800/90 backdrop-blur-sm rounded-2xl p-6 border border-gray-200 dark:border-gray-700">
|
||||||
|
<Heading as="h2" size="4" class="mb-6">Contributors</Heading>
|
||||||
|
|
||||||
|
<div class="space-y-4">
|
||||||
|
{contributors.map((contributor, index) => (
|
||||||
|
<div class="flex items-center gap-4">
|
||||||
|
<div class="w-10 h-10 rounded-full bg-gradient-to-br from-mana-blue to-purple-500 flex items-center justify-center text-white font-semibold">
|
||||||
|
{contributor.name.charAt(0)}
|
||||||
|
</div>
|
||||||
|
<div class="flex-1">
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<Text weight="semibold">{contributor.name}</Text>
|
||||||
|
{contributor.handle && (
|
||||||
|
<Text size="sm" class="text-gray-500">@{contributor.handle}</Text>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center gap-4 mt-1">
|
||||||
|
<Text size="sm" class="text-gray-500">
|
||||||
|
<Icon name="mdi:source-commit" class="w-4 h-4 inline mr-1" />
|
||||||
|
{contributor.commits} Commits
|
||||||
|
</Text>
|
||||||
|
<div class="flex-1 h-2 bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden">
|
||||||
|
<div
|
||||||
|
class="h-full bg-gradient-to-r from-green-500 to-emerald-500 rounded-full"
|
||||||
|
style={`width: ${(contributor.commits / totalCommits) * 100}%`}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Container>
|
||||||
|
</Section>
|
||||||
|
|
||||||
|
<!-- Recent Activity -->
|
||||||
|
<Section spacing="large" class="relative">
|
||||||
|
<Container>
|
||||||
|
<Heading as="h2" size="3" class="mb-8">Letzte Aktivität</Heading>
|
||||||
|
|
||||||
|
<div class="space-y-4">
|
||||||
|
{sortedPosts.slice(-5).reverse().map((post) => (
|
||||||
|
<a
|
||||||
|
href={`/devlog/${post.slug}`}
|
||||||
|
class="block bg-white/90 dark:bg-gray-800/90 backdrop-blur-sm rounded-xl p-4 border border-gray-200 dark:border-gray-700 hover:border-mana-blue/50 transition-colors"
|
||||||
|
>
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<div>
|
||||||
|
<Text weight="semibold" class="mb-1">{post.data.title}</Text>
|
||||||
|
<div class="flex items-center gap-4 text-sm text-gray-500">
|
||||||
|
<span>
|
||||||
|
<Icon name="mdi:calendar" class="w-4 h-4 inline mr-1" />
|
||||||
|
{formatDate(post.data.date)}
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
<Icon name="mdi:source-commit" class="w-4 h-4 inline mr-1" />
|
||||||
|
{post.data.commits} Commits
|
||||||
|
</span>
|
||||||
|
{post.data.stats && (
|
||||||
|
<span class="text-green-600 dark:text-green-400">
|
||||||
|
+{formatNumber(post.data.stats.linesAdded)}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
{post.data.stats && (
|
||||||
|
<span class="text-red-600 dark:text-red-400">
|
||||||
|
-{formatNumber(post.data.stats.linesRemoved)}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Icon name="mdi:chevron-right" class="w-5 h-5 text-gray-400" />
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</Container>
|
||||||
|
</Section>
|
||||||
|
|
||||||
|
<Footer />
|
||||||
|
</div>
|
||||||
|
</Layout>
|
||||||
|
|
@ -106,6 +106,25 @@ const formatDate = (date: Date) => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Container class="relative z-10">
|
<Container class="relative z-10">
|
||||||
|
<!-- Activity Link -->
|
||||||
|
<div class="max-w-4xl mx-auto mb-8">
|
||||||
|
<a
|
||||||
|
href="/devlog/activity"
|
||||||
|
class="group flex items-center justify-between bg-gradient-to-r from-green-500/10 to-emerald-500/10 hover:from-green-500/20 hover:to-emerald-500/20 border border-green-500/30 rounded-xl p-4 transition-all"
|
||||||
|
>
|
||||||
|
<div class="flex items-center gap-3">
|
||||||
|
<div class="w-10 h-10 rounded-lg bg-gradient-to-br from-green-500/20 to-emerald-500/20 flex items-center justify-center">
|
||||||
|
<Icon name="mdi:chart-timeline-variant" class="w-5 h-5 text-green-600 dark:text-green-400" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Text weight="semibold" class="text-green-700 dark:text-green-300">Aktivitäts-Übersicht</Text>
|
||||||
|
<Text size="sm" class="text-green-600/70 dark:text-green-400/70">Contribution Grid, Stats & Contributors</Text>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Icon name="mdi:arrow-right" class="w-5 h-5 text-green-600 dark:text-green-400 group-hover:translate-x-1 transition-transform" />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="max-w-4xl mx-auto space-y-8">
|
<div class="max-w-4xl mx-auto space-y-8">
|
||||||
{
|
{
|
||||||
sortedPosts.map((post) => {
|
sortedPosts.map((post) => {
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,23 @@ tags:
|
||||||
featured: true # oder false
|
featured: true # oder false
|
||||||
commits: 42 # Anzahl der Commits an diesem Tag
|
commits: 42 # Anzahl der Commits an diesem Tag
|
||||||
readTime: 15 # Geschätzte Lesezeit in Minuten
|
readTime: 15 # Geschätzte Lesezeit in Minuten
|
||||||
|
|
||||||
|
# Extended Stats für Aktivitätsgrid
|
||||||
|
stats:
|
||||||
|
filesChanged: 289
|
||||||
|
linesAdded: 17857
|
||||||
|
linesRemoved: 2113
|
||||||
|
|
||||||
|
# Contributors (wer hat an diesem Tag gearbeitet)
|
||||||
|
contributors:
|
||||||
|
- name: 'Till Schneider'
|
||||||
|
handle: 'Till-JS'
|
||||||
|
commits: 42
|
||||||
|
|
||||||
|
# Working Hours (für Aktivitätsgrid)
|
||||||
|
workingHours:
|
||||||
|
start: '2026-01-30T11:00'
|
||||||
|
end: '2026-01-31T11:00'
|
||||||
---
|
---
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -56,13 +73,26 @@ readTime: 15 # Geschätzte Lesezeit in Minuten
|
||||||
4. **Zusammenfassung** - Tabelle mit Bereichen, Commit-Anzahl und Highlights
|
4. **Zusammenfassung** - Tabelle mit Bereichen, Commit-Anzahl und Highlights
|
||||||
5. **Nächste Schritte** - Was als nächstes geplant ist
|
5. **Nächste Schritte** - Was als nächstes geplant ist
|
||||||
|
|
||||||
## Commit-Zählung
|
## Git-Stats abrufen
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Commits für einen Arbeitstag zählen (11:00 - 11:00 des Folgetages)
|
# Commits für einen Arbeitstag zählen (11:00 - 11:00 des Folgetages)
|
||||||
git log --since="YYYY-MM-DD 11:00" --until="YYYY-MM-DD+1 10:59" --oneline | wc -l
|
git log --since="YYYY-MM-DD 11:00" --until="YYYY-MM-DD+1 11:00" --oneline | wc -l
|
||||||
|
|
||||||
|
# Detaillierte Stats (files, insertions, deletions)
|
||||||
|
git log --since="YYYY-MM-DD 11:00" --until="YYYY-MM-DD+1 11:00" --shortstat --format="" | \
|
||||||
|
awk '{files+=$1; ins+=$4; del+=$6} END {print "files:", files, "insertions:", ins, "deletions:", del}'
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Aktivitätsgrid
|
||||||
|
|
||||||
|
Die Aktivitätsgrid-Seite ist unter `/devlog/activity` erreichbar und zeigt:
|
||||||
|
|
||||||
|
- **GitHub-Style Contribution Grid** - Aktivität der letzten 365 Tage
|
||||||
|
- **Gesamt-Statistiken** - Commits, Dateien, Lines Added/Removed
|
||||||
|
- **Contributors** - Wer hat wie viel beigetragen
|
||||||
|
- **Letzte Aktivität** - Die 5 neuesten Devlogs
|
||||||
|
|
||||||
## Best Practices
|
## Best Practices
|
||||||
|
|
||||||
- Technische Details mit Code-Beispielen und Architektur-Diagrammen illustrieren
|
- Technische Details mit Code-Beispielen und Architektur-Diagrammen illustrieren
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue