Skip to content

Commit 452ad03

Browse files
Merge branch 'main' into offline-mode
2 parents a3d0acb + 132d65b commit 452ad03

56 files changed

Lines changed: 1586 additions & 393 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.env.production

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,6 @@
33
NEXT_PUBLIC_API_URL=/api/
44
NEXT_PUBLIC_SLACK_CLIENT_ID=10831824934.7404945710466
55
NEXT_PUBLIC_GOOGLE_ANALYTICS_ID=G-1BFJYBDC76
6-
NEXT_PUBLIC_RECAPTCHA_KEY=6Le63OUqAAAAABxxDrbaU9OywDLLHqutVwbw7a9d
6+
NEXT_PUBLIC_RECAPTCHA_KEY=6Le63OUqAAAAABxxDrbaU9OywDLLHqutVwbw7a9d
7+
8+
ENV_FILE=.env.production

.env.test

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,20 @@
1-
NEXT_PUBLIC_API_URL=http://localhost:3000/api
1+
NEXTAUTH_URL=http://localhost:3000/
2+
NEXTAUTH_SECRET=testsecret
3+
4+
NEXT_PUBLIC_API_URL=/api/
25

36
DEVELOPER_EMAILS=["test@gmail.com"]
47

58
TOA_URL=https://example.com
69
TOA_APP_ID=123
710
TOA_KEY=456
811

9-
DEFAULT_IMAGE=https://example.com/default.jpg
12+
DEFAULT_IMAGE=https://example.com/default.jpg
13+
14+
BASE_URL_FOR_PLAYWRIGHT=http://localhost:3000/
15+
ENABLE_TEST_SIGNIN_ROUTE=true
16+
FALLBACK_MONGODB_URI=mongodb://127.0.0.1:27017/?directConnection=true&serverSelectionTimeoutMS=2000
17+
18+
ENV_FILE=.env.test
19+
20+
DB=playwright_tests

.github/workflows/ci.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,9 @@ jobs:
6666

6767
- name: Lint
6868
run: npm run lint
69+
70+
e2e_test:
71+
uses: ./.github/workflows/e2e_test.yml
72+
permissions:
73+
contents: read
74+
pull-requests: write

.github/workflows/e2e_test.yml

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
name: Playwright Tests
2+
on: [workflow_dispatch, workflow_call]
3+
jobs:
4+
e2e_tests:
5+
timeout-minutes: 60
6+
runs-on: ubuntu-latest
7+
strategy:
8+
fail-fast: false
9+
matrix:
10+
# Make sure to require each shard in GitHub!
11+
shardIndex: [1, 2, 3, 4]
12+
shardTotal: [4]
13+
steps:
14+
- uses: actions/checkout@v4
15+
16+
- uses: actions/setup-node@v4
17+
with:
18+
node-version: lts/*
19+
20+
- name: Install dependencies
21+
run: npm ci
22+
23+
- name: Install Playwright browsers
24+
run: npx playwright install --with-deps
25+
26+
- name: Start MongoDB
27+
uses: supercharge/mongodb-github-action@1.12.0
28+
with:
29+
mongodb-version: "8.0"
30+
31+
- name: Run Playwright tests
32+
run: npx cross-env NODE_ENV=test playwright test --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }}
33+
34+
- name: Upload blob report to GitHub Actions Artifacts
35+
if: ${{ !cancelled() }}
36+
uses: actions/upload-artifact@v4
37+
with:
38+
name: blob-report-${{ matrix.shardIndex }}
39+
path: blob-report
40+
retention-days: 1
41+
42+
merge_reports:
43+
# Merge reports after playwright-tests, even if some shards have failed
44+
if: ${{ !cancelled() }}
45+
needs: [e2e_tests]
46+
47+
runs-on: ubuntu-latest
48+
steps:
49+
- uses: actions/checkout@v4
50+
- uses: actions/setup-node@v4
51+
with:
52+
node-version: lts/*
53+
- name: Install dependencies
54+
run: npm ci
55+
56+
- name: Download blob reports from GitHub Actions Artifacts
57+
uses: actions/download-artifact@v4
58+
with:
59+
path: all-blob-reports
60+
pattern: blob-report-*
61+
merge-multiple: true
62+
63+
- name: Merge into HTML Report
64+
run: npx playwright merge-reports --reporter html ./all-blob-reports
65+
66+
- name: Upload HTML report
67+
uses: actions/upload-artifact@v4
68+
with:
69+
name: html-report--attempt-${{ github.run_attempt }}
70+
path: playwright-report
71+
retention-days: 14

.gitignore

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,11 @@ next-env.d.ts
4141

4242
# PWA
4343
public/sw.js
44-
public/swe-worker*
44+
public/swe-worker*
45+
46+
# Playwright
47+
node_modules/
48+
/test-results/
49+
/playwright-report/
50+
/blob-report/
51+
/playwright/.cache/

.vscode/extensions.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
"pmneo.tsimporter",
99
"austenc.tailwind-docs",
1010
"bradlc.vscode-tailwindcss",
11-
"Orta.vscode-jest"
11+
"Orta.vscode-jest",
12+
"ms-playwright.playwright"
1213
]
1314
}

components/Avatar.tsx

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { levelToClassName } from "@/lib/Xp";
33
import { BsGearFill } from "react-icons/bs";
44

55
export default function Avatar(props: {
6-
user?: { image: string | undefined; level: number; admin?: boolean };
6+
user?: { image: string | undefined; level?: number; admin?: boolean };
77
scale?: string | undefined; // Use "scale-75" for 75% scale, etc.
88
imgHeightOverride?: string | undefined;
99
showLevel?: boolean | undefined;
@@ -13,6 +13,7 @@ export default function Avatar(props: {
1313
className?: string | undefined;
1414
online?: boolean;
1515
gearSize?: number;
16+
altText?: string;
1617
}) {
1718
const { session, status } = useCurrentSession();
1819
const user = props.user ?? session?.user;
@@ -24,8 +25,8 @@ export default function Avatar(props: {
2425
<div
2526
className={`avatar ${props.online && "online"} ${props.scale} ${props.className} ${props.animation}`}
2627
>
27-
{(props.showLevel ?? true) && (
28-
<div className="absolute z-10 bg-base-100 rounded-tl-xl rounded-br-xl h-6 w-14 text-center text-sm font-semibold">
28+
{props.showLevel && (
29+
<div className="absolute bg-base-100 rounded-tl-xl rounded-br-xl h-6 w-14 text-center text-sm font-semibold">
2930
LVL: {user?.level}
3031
</div>
3132
)}
@@ -34,12 +35,12 @@ export default function Avatar(props: {
3435
>
3536
<img
3637
src={image}
37-
alt={"Avatar"}
38+
alt={props.altText ?? "Avatar"}
3839
onClick={props.onClick}
3940
></img>
4041
</div>
4142
{admin ? (
42-
<div className="absolute z-10 -bottom-2 -left-2 text-slate-300 animate-spin-slow">
43+
<div className="absolute -bottom-2 -left-2 text-slate-300 animate-spin-slow">
4344
<BsGearFill size={props.gearSize ?? 36}></BsGearFill>
4445
</div>
4546
) : (

components/Card.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export default function Card(props: CardProps) {
1414

1515
return (
1616
<div
17+
title={title}
1718
className={`card bg-base-200 shadow-xl w-2/3 max-sm:w-full ${className}`}
1819
>
1920
{color ? (

components/EditAvatarModal.tsx

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import { useState } from "react";
2+
import Card from "./Card";
3+
import ClientApi from "@/lib/api/ClientApi";
4+
import Avatar from "./Avatar";
5+
import Image from "next/image";
6+
import { Session } from "inspector/promises";
7+
import toast from "react-hot-toast";
8+
9+
const api = new ClientApi();
10+
export default function EditAvatarModal(props: {
11+
currentImg: string;
12+
close: () => void;
13+
}) {
14+
const [newAvatar, setNewAvatar] = useState<string>(props.currentImg);
15+
16+
async function updateAvatar() {
17+
toast.promise(
18+
api.changePFP(newAvatar).then(() => location.reload()),
19+
{
20+
loading: "Updating profile picture...",
21+
success: "Successfully updated profile picture!",
22+
error: "Failed to update profile picture!",
23+
},
24+
);
25+
}
26+
27+
return (
28+
<dialog
29+
open={true}
30+
className="modal"
31+
>
32+
<Card
33+
title="Edit Avatar"
34+
coloredTop="bg-secondary"
35+
>
36+
<div className="my-9 flex justify-center w-full">
37+
<Avatar
38+
user={{ image: newAvatar }}
39+
scale="scale-150"
40+
altText="New Avatar"
41+
showLevel={false}
42+
/>
43+
</div>
44+
45+
<input
46+
defaultValue={props.currentImg}
47+
className="input"
48+
onChange={(e) => setNewAvatar(e.target.value)}
49+
placeholder="Enter new avatar url"
50+
/>
51+
<div className="flex gap-2 justify-start w-full">
52+
<button
53+
className="btn btn-primary mt-2"
54+
onClick={updateAvatar}
55+
>
56+
Save
57+
</button>
58+
<button
59+
className="btn btn-accent mt-2"
60+
onClick={props.close}
61+
>
62+
Cancel
63+
</button>
64+
</div>
65+
</Card>
66+
</dialog>
67+
);
68+
}

components/SignInMenu.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,13 @@ function SignInCard() {
5959
<div className="card-body">
6060
<h1 className="card-title">Sign In</h1>
6161
{error && <p className="text-error">{error}</p>}
62-
<p>Choose a login provider</p>
62+
<p className="italic">Choose a login provider</p>
63+
<span>
64+
You currently <span className="text-red-500">have</span> to sign-in
65+
using either your{" "}
66+
<span className="text-green-400">original sign-in method</span> or
67+
your <span className="text-green-400">email.</span>
68+
</span>
6369
<div className="divider" />
6470

6571
<button

0 commit comments

Comments
 (0)