This commit is contained in:
2023-12-19 21:59:44 +00:00
parent ef5ef8001f
commit 75dfd44321
6 changed files with 166 additions and 21 deletions
+15
View File
@@ -0,0 +1,15 @@
.react-calendar-heatmap .color-gitlab-0 {
fill: #ededed;
}
.react-calendar-heatmap .color-gitlab-1 {
fill: #acd5f2;
}
.react-calendar-heatmap .color-gitlab-2 {
fill: #7fa8d1;
}
.react-calendar-heatmap .color-gitlab-3 {
fill: #49729b;
}
.react-calendar-heatmap .color-gitlab-4 {
fill: #254e77;
}
+100
View File
@@ -0,0 +1,100 @@
"use client";
import {Card, Title} from "@tremor/react";
import {useEffect, useRef, useState} from "react";
import useSWR from "swr";
import {fetcher} from "@/app/utils";
import * as R from 'ramda';
import * as dFns from 'date-fns';
import CalendarHeatmap from 'react-calendar-heatmap';
import 'react-calendar-heatmap/dist/styles.css';
import './calendar-styles.css'
import * as dns from "dns";
import { Tooltip } from 'react-tooltip';
const initialDate = dFns.parseISO('2023-12-15T00:00:00.000Z')
const endDate = dFns.parseISO('2024-01-20T00:00:00.000Z')
const projectIds = [
195482340,
195519024,
195518593,
195754611,
];
function useCalendarData() {
const {
data: timeEntries,
error,
isLoading,
} = useSWR<{
raw_json: {
start: string,
seconds: number,
}
}[]>(`http://cosmos:8074/time_entry?select=raw_json&start=gt.${dFns.formatISO(initialDate)}&project_id=in.(${projectIds.join(',')})`, fetcher, {});
const [data, setData] = useState<{
date: Date,
count: number,
}[]>([]);
useEffect(() => {
if (timeEntries == undefined) return;
// Group by day, sum up seconds
const grouped = R.groupBy((entry) => {
return dFns.formatISO(dFns.parseISO(entry.raw_json.start), 'yyyy-MM-dd');
}, timeEntries);
const summed = R.mapObjIndexed((entries) => {
return R.sum((entries ?? []).map((entry) => entry.raw_json.seconds))
}, grouped);
setData(Object.entries(summed)
.map(([key, value]) => ({
date: dFns.parseISO(key),
count: value / (60 * 60),
})));
}, [timeEntries]);
return data
}
export function CalendarOverviewCard() {
const data = useCalendarData();
const containerRef = useRef<HTMLDivElement>(null);
const [height, setHeight] = useState(200);
// Fix aspect ratio of the heatmap to be 2:1
useEffect(() => {
const container = containerRef.current;
if (container) {
const resizeObserver = new ResizeObserver(() => {
const width = container.clientWidth;
setHeight(width / 5);
});
resizeObserver.observe(container);
return () => resizeObserver.disconnect();
}
}, [containerRef]);
return <Card className="col-span-1">
<Tooltip id="calendar-tooltip"/>
<Title>Overview</Title>
<CalendarHeatmap
showWeekdayLabels={true}
startDate={initialDate}
endDate={endDate}
values={data}
tooltipDataAttrs={(value: any) => {
return value.count ? {
'data-tooltip-id': `calendar-tooltip`,
'data-tooltip-content': `${value.count.toFixed(2)} hours`
} : undefined;
}}
/>
</Card>
}
+1 -13
View File
@@ -2,18 +2,6 @@
@tailwind components;
@tailwind utilities;
:root {
--foreground-rgb: 0, 0, 0;
/*--background-start-rgb: 214, 219, 220;*/
/*--background-end-rgb: 255, 255, 255;*/
}
@media (prefers-color-scheme: dark) {
:root {
--foreground-rgb: 255, 255, 255;
}
}
body {
color: rgb(var(--foreground-rgb));
@apply dark:bg-slate-800 bg-white;
}
+3 -8
View File
@@ -1,10 +1,10 @@
import {SubjectComparisonCard, SubjectOverviewCard} from "@/app/a.client";
import {Title} from "@tremor/react";
import {CalendarOverviewCard} from "@/app/calendarOverviewCard";
export default function Home() {
return (
<main className="m-6">
<h1 className="text-3xl font-semibold font-black">Revision Tracker</h1>
<h1 className="text-3xl font-semibold text-slate-900 dark:text-white my-2">Revision Tracker</h1>
<div className="grid gap-5 grid-cols-4">
<SubjectOverviewCard
@@ -25,12 +25,7 @@ export default function Home() {
projectId={195754611}
/>
<SubjectComparisonCard projectIds={[
195482340,
195519024,
195518593,
195754611,
]}/>
<CalendarOverviewCard/>
</div>
</main>