Skip to content

Commit 6e183cb

Browse files
committed
feat: implement deployment workflow and Docker setup for GitHub Pages
1 parent 125ff2a commit 6e183cb

File tree

7 files changed

+117
-7
lines changed

7 files changed

+117
-7
lines changed

.github/workflows/deploy.yml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
name: Deploy to GitHub Pages
2+
3+
on:
4+
push:
5+
branches: [main]
6+
workflow_dispatch:
7+
8+
permissions:
9+
contents: read
10+
pages: write
11+
id-token: write
12+
13+
jobs:
14+
build:
15+
runs-on: ubuntu-latest
16+
steps:
17+
- name: Checkout
18+
uses: actions/checkout@v4
19+
20+
- name: Setup Bun
21+
uses: oven-sh/setup-bun@v1
22+
with:
23+
bun-version: latest
24+
25+
- name: Install dependencies
26+
run: bun install
27+
28+
- name: Build
29+
run: bun run build
30+
31+
- name: Setup Pages
32+
uses: actions/configure-pages@v4
33+
34+
- name: Upload artifact
35+
uses: actions/upload-pages-artifact@v2
36+
with:
37+
path: ./dist
38+
39+
deploy:
40+
environment:
41+
name: github-pages
42+
url: ${{ steps.deployment.outputs.page_url }}
43+
runs-on: ubuntu-latest
44+
needs: build
45+
steps:
46+
- name: Deploy to GitHub Pages
47+
id: deployment
48+
uses: actions/deploy-pages@v3

Dockerfile

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Multi-stage build for production
2+
FROM oven/bun:1-alpine as builder
3+
4+
WORKDIR /app
5+
COPY package.json bun.lockb ./
6+
RUN bun install --frozen-lockfile
7+
8+
COPY . .
9+
RUN bun run build
10+
11+
# Production stage
12+
FROM nginx:alpine
13+
14+
COPY --from=builder /app/dist /usr/share/nginx/html
15+
COPY nginx.conf /etc/nginx/conf.d/default.conf
16+
17+
EXPOSE 80
18+
CMD ["nginx", "-g", "daemon off;"]

deploy.sh

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#!/bin/bash
2+
3+
# Simple deployment script
4+
# Upload the dist folder to your server
5+
6+
# Example using scp:
7+
# scp -r dist/* [email protected]:/var/www/html/
8+
9+
# Example using rsync:
10+
# rsync -av --delete dist/ [email protected]:/var/www/html/
11+
12+
# For nginx, make sure your server config serves static files:
13+
# server {
14+
# listen 80;
15+
# server_name your-domain.com;
16+
# root /var/www/html;
17+
# index index.html;
18+
#
19+
# location / {
20+
# try_files $uri $uri/ /index.html;
21+
# }
22+
# }

nginx.conf

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
server {
2+
listen 80;
3+
server_name localhost;
4+
root /usr/share/nginx/html;
5+
index index.html;
6+
7+
# Handle client-side routing
8+
location / {
9+
try_files $uri $uri/ /index.html;
10+
}
11+
12+
# Cache static assets
13+
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
14+
expires 1y;
15+
add_header Cache-Control "public, immutable";
16+
}
17+
18+
# Security headers
19+
add_header X-Frame-Options "SAMEORIGIN" always;
20+
add_header X-Content-Type-Options "nosniff" always;
21+
add_header Referrer-Policy "no-referrer-when-downgrade" always;
22+
}

src/components/EventTable.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ export function EventTable({ events, filters, showDelays }: EventTableProps) {
8787
key={`${event.id}-${column.key}`}
8888
className="px-3 py-2 text-text font-mono text-xs whitespace-nowrap"
8989
>
90-
{column.key === "eventType" ? (
90+
{column.key === "eventType" && "eventType" in event ? (
9191
<div className="flex items-center space-x-2">
9292
<div
9393
className="w-2 h-2 rounded-full flex-shrink-0"
@@ -98,10 +98,10 @@ export function EventTable({ events, filters, showDelays }: EventTableProps) {
9898
],
9999
}}
100100
/>
101-
<span>{getCellValue(event, column)}</span>
101+
<span>{getCellValue(event as EventData, column)}</span>
102102
</div>
103103
) : (
104-
getCellValue(event, column)
104+
"eventType" in event ? getCellValue(event as EventData, column) : "-"
105105
)}
106106
</td>
107107
))}

src/components/Timeline.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ interface TimelineBar {
1212
duration: number;
1313
color: string;
1414
level: number; // Row level for overlapping bars
15-
type: "keypress" | "input";
15+
type: "keypress" | "input" | "composition";
1616
}
1717

1818
export function Timeline({ events }: TimelineProps) {

src/hooks/useKeyboardEvents.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -197,11 +197,11 @@ export function useKeyboardEvents() {
197197
const importEvents = useCallback((importedEvents: EventData[]) => {
198198
setEvents(importedEvents);
199199
// Reset event ID to the highest ID in imported events + 1
200-
const maxId = importedEvents.reduce((max, event) => Math.max(max, event.eventId), 0);
200+
const maxId = importedEvents.reduce((max, event) => Math.max(max, event.id), 0);
201201
eventIdRef.current = maxId + 1;
202-
// Reset timestamps - they'll be relative to the imported events
202+
// Reset timestamps - use the first event's timestamp as the new start time
203203
const firstEvent = importedEvents[0];
204-
startTimeRef.current = firstEvent ? firstEvent.timestamp - firstEvent.relativeTime : 0;
204+
startTimeRef.current = firstEvent ? firstEvent.timestamp : 0;
205205
keydownTimestamps.current = {};
206206
}, []);
207207

0 commit comments

Comments
 (0)