Compare commits

..
7 Commits
Author SHA1 Message Date
joshuacoles 026d0cfd56 Add macos build for arm
Build and Publish Docker Container / build-arm (push) Successful in 1m50s
Build and Publish Docker Container / build (push) Successful in 3m44s
2024-03-04 19:46:13 +00:00
joshuacoles 1a14485c57 Update reads to toggl database 2024-03-04 19:46:07 +00:00
joshuacoles 50730a2b09 Simplify calendar code 2024-03-03 18:57:03 +00:00
joshuacoles 9fc14cffd0 Add Caddyfile to gitignore 2024-03-03 18:47:18 +00:00
joshuacoles e534506894 Update build.yml 2024-02-28 17:20:42 +00:00
joshuacoles 89558cdd1a Remove unnecessary user interaction with donut chart
Build and Publish Docker Container / build (push) Successful in 4m22s
2024-02-28 17:18:56 +00:00
joshuacoles d6b319e6a5 Colour weekends differently by default 2024-02-28 16:49:35 +00:00
7 changed files with 95 additions and 72 deletions
+27 -1
View File
@@ -25,9 +25,35 @@ jobs:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and Push Docker image -- finn-board
- name: Build and Push Docker image
uses: docker/build-push-action@675965c0e16f1a0f94ecafff969d8c966f92c17b
with:
context: .
push: true
tags: git.joshuacoles.me/joshuacoles/revision-ui:latest
build-arm:
runs-on: macos-latest
container:
image: catthehacker/ubuntu:act-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Login to Docker
uses: docker/login-action@v1
with:
registry: git.joshuacoles.me
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and Push Docker image
uses: docker/build-push-action@675965c0e16f1a0f94ecafff969d8c966f92c17b
with:
context: .
push: true
tags: git.joshuacoles.me/joshuacoles/revision-ui:arm
+3
View File
@@ -40,3 +40,6 @@ next-env.d.ts
# Private env files
.env
# Caddyfile for local development when testing weird deploys
/Caddyfile
+8 -2
View File
@@ -8,7 +8,12 @@ export type DonutChartData = {
value: number;
}[];
export function Donut({data, centerLabel, formatter, hoverSuffix}: {
export function Donut({
data,
centerLabel,
formatter,
hoverSuffix
}: {
data: DonutChartData,
formatter: (value: number) => string,
centerLabel: string,
@@ -71,12 +76,13 @@ export function Donut({data, centerLabel, formatter, hoverSuffix}: {
strokeWidth="3"
strokeDasharray={`${value * normalisingFactor} ${100 - value * normalisingFactor}`}
strokeDashoffset={100 - (offset * normalisingFactor) + 25}
style={{outline: 'none'}}
/>
)
})
}
<g className="chart-text">
<g className="chart-text" style={{ userSelect: 'none'}}>
<text x="50%" y="50%" className="chart-number">
{formatter(total)}
</text>
+8 -8
View File
@@ -40,33 +40,33 @@ function GitHubCalendarHeatmap({
const dayGoalTime = goal;
const weekGoalTime = 5 * dayGoalTime;
const getColorForValue = (value: number, goalTime: number): string => {
const getColorForValue = (value: number, goalTime: number, zeroColor: string): string => {
const buckets = [
{
min: -Infinity,
max: 0,
color: '#eeeeee'
color: zeroColor,
},
{
min: 0,
max: 0.40,
color: '#d6e685'
color: '#d6e685',
},
{
min: 0.40,
max: 0.50,
color: '#8cc665'
color: '#8cc665',
},
{
min: 0.50,
max: 0.90,
color: '#44a340'
color: '#44a340',
},
{
min: 0.90,
// If penalising overtime, the max is 1.125, otherwise it's infinity (ie this is the last bucket)
max: penaliseOvertime ? 1.125 : Infinity,
color: '#1e6823'
color: '#1e6823',
},
{
min: 1.125,
@@ -116,7 +116,7 @@ function GitHubCalendarHeatmap({
const dayOfWeek = (date.getDay() + 6) % 7;
const x = weekIndex * (squareSize + padding);
const y = dayOfWeek * (squareSize + padding);
const color = getColorForValue(count, dayGoalTime);
const color = getColorForValue(count, dayGoalTime, dFns.isWeekend(date) ? '#d4d4d4' : '#eeeeee');
return (
<rect
@@ -137,7 +137,7 @@ function GitHubCalendarHeatmap({
const x = weekIndex * (squareSize + padding);
const y = 7 * (squareSize + padding) + weekTotalPadding; // Position for the week total
const count = getWeekTotal(weekIndex);
const color = getColorForValue(count, weekGoalTime);
const color = getColorForValue(count, weekGoalTime, '#eeeeee');
return (
<rect
+2 -13
View File
@@ -5,7 +5,7 @@ import {Tooltip} from 'react-tooltip';
import {Data} from "@/data/fetchData";
import HeatMap from "@/components/HeatMap";
function useCalendarData(data: Data, initialDate: Date, endDate: Date) {
function useCalendarData(data: Data) {
const timeEntries = data.timeEntries;
// Group by day, sum up seconds
@@ -17,17 +17,6 @@ function useCalendarData(data: Data, initialDate: Date, endDate: Date) {
return R.sum((entries ?? []).map((entry) => entry.duration))
}, grouped);
// Fill in missing days, hacky
dFns.eachDayOfInterval({
start: initialDate,
end: endDate,
}).forEach((date) => {
const key = dFns.formatISO(date);
if (summed[key] == undefined) {
summed[key] = 0;
}
})
return Object.entries(summed)
.map(([key, value]) => ({
date: dFns.parseISO(key),
@@ -50,7 +39,7 @@ export function CalendarOverviewCard({
}) {
const initialDate = dFns.parseISO(startTime);
const endDate = dFns.parseISO(endTime);
const calendarData = useCalendarData(data, initialDate, endDate);
const calendarData = useCalendarData(data);
return <Card className="col-span-1">
<Tooltip id="calendar-tooltip"/>
+10 -11
View File
@@ -1,4 +1,4 @@
import type {ColumnType, JSONColumnType} from "kysely";
import type {ColumnType} from "kysely";
export type Generated<T> = T extends ColumnType<infer S, infer I, infer U>
? ColumnType<S, I | undefined, U>
@@ -32,13 +32,13 @@ export interface Client {
export interface Project {
active: boolean;
client_id: number | null;
color: string;
id: Generated<number>;
name: string;
raw_json: JSONColumnType<{
color: string;
id: number;
name: string;
}>;
raw_json: Json;
server_created_at: Timestamp;
server_deleted_at: Timestamp | null;
server_updated_at: Timestamp;
toggl_id: Int8;
workspace_id: Int8;
}
@@ -47,13 +47,12 @@ export interface TimeEntry {
description: string;
id: Generated<number>;
project_id: Int8 | null;
raw_json: JSONColumnType<{
start: string;
end: string;
seconds: number;
}>;
raw_json: Json;
server_deleted_at: Timestamp | null;
server_updated_at: Timestamp;
start: Timestamp;
stop: Timestamp;
tags: Generated<Json>;
toggl_id: Int8;
}
+10 -10
View File
@@ -52,12 +52,12 @@ export async function getData(config: OverviewConfig): Promise<Data> {
let projectIds = config.subjects.map((subject) => subject.projectId.toString());
const projects = await db.selectFrom('project')
.select('raw_json')
.where('project.toggl_id', 'in', projectIds)
.execute();
.select(['toggl_id', 'name', 'color'])
.where('toggl_id', 'in', projectIds)
.execute()
const timeEntries = await db.selectFrom('time_entry')
.select(['project_id', 'raw_json'])
.select(['project_id', 'start', 'stop'])
.where('project_id', 'in', projectIds)
.where('start', '>', dFns.parseISO(config.timePeriod.start))
.where('start', '<', dFns.parseISO(config.timePeriod.end))
@@ -65,16 +65,16 @@ export async function getData(config: OverviewConfig): Promise<Data> {
return {
projects: projects.map((project) => ({
projectId: project.raw_json.id,
name: project.raw_json.name,
color: project.raw_json.color,
projectId: parseInt(project.toggl_id),
name: project.name,
color: project.color,
})),
timeEntries: timeEntries.map((timeEntry) => ({
projectId: parseInt(timeEntry.project_id!),
start: timeEntry.raw_json.start,
end: timeEntry.raw_json.end,
duration: timeEntry.raw_json.seconds,
start: dFns.formatISO(timeEntry.start),
end: dFns.formatISO(timeEntry.stop),
duration: dFns.differenceInSeconds(timeEntry.stop, timeEntry.start)
})),
}
}