Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
88 commits
Select commit Hold shift + click to select a range
3f42ccd
get campaigns by org and campaign slugs
KavikaPalletenne Aug 13, 2025
098f96e
Update .gitignore
KavikaPalletenne Aug 13, 2025
b965ccc
campaign info page
KavikaPalletenne Aug 13, 2025
24543e4
apply page
KavikaPalletenne Aug 13, 2025
9127e93
Serialize i64 IDs as strings
KavikaPalletenne Aug 13, 2025
1b09a10
update all array_agg of json to include to_jsonb
KavikaPalletenne Aug 13, 2025
1039f86
display application questions
KavikaPalletenne Aug 13, 2025
a22487e
fix types for question data in fe
KavikaPalletenne Aug 13, 2025
788dbc0
Update seeder.rs
KavikaPalletenne Aug 16, 2025
5932c71
fetch and show questions for selected roles
KavikaPalletenne Aug 16, 2025
64aca23
fix width of questions
KavikaPalletenne Aug 16, 2025
9ff1e52
smaller role selection buttons
KavikaPalletenne Aug 16, 2025
bc9f5ab
create or get application on page load
KavikaPalletenne Aug 20, 2025
c45e7ee
fetch answers for common & role questions
KavikaPalletenne Aug 20, 2025
22b8650
get answers
KavikaPalletenne Aug 21, 2025
8971497
fix `AnswerData` enum tagging
KavikaPalletenne Aug 21, 2025
7988c0d
first version of AGENTS.md file
KavikaPalletenne Aug 26, 2025
be528e9
handle answer update & delete
KavikaPalletenne Aug 27, 2025
a8eebfa
fix new answer being deleted
KavikaPalletenne Aug 27, 2025
042c9b3
don't require login for campaign
KavikaPalletenne Sep 23, 2025
345055a
application role preferences & admin review setup
KavikaPalletenne Sep 25, 2025
2bbc28f
Update yarn.lock
KavikaPalletenne Sep 25, 2025
fddd147
update to node 24
KavikaPalletenne Sep 25, 2025
18bce49
endpoints for getting & updating application ratings
KavikaPalletenne Sep 30, 2025
91ae292
Chaos 571 - Add Notion-style form editor (#575)
peternuyn Sep 30, 2025
f13c7de
update lockfile
gyoumi Oct 1, 2025
730e814
integrate application review with the backend
Oct 4, 2025
c10f9cc
fixing subcom application integration with backend including the auto…
Oct 6, 2025
dcaa246
update backend readme to include `libssl-dev` install
KavikaPalletenne Oct 7, 2025
c1a27b1
update frontend lock files
KavikaPalletenne Oct 7, 2025
4fbe202
Email templates (purely frontend) (#579)
remyjelee Oct 9, 2025
fdc77a4
migrated to bun
gyoumi Oct 10, 2025
26745b7
migrated to bun
gyoumi Oct 10, 2025
23d9469
replaced all mentions of yarn with bun
gyoumi Oct 10, 2025
94d5fe0
Chaos 577 create campaign be fe (#581)
Plebbaroni Oct 23, 2025
73dda50
fix spelling
KavikaPalletenne Oct 23, 2025
77a5053
feat: added published flag to campaign (#589)
AlexMIaoPU Oct 28, 2025
68a386d
588 fe dev only buttons for login + Added get_all orgs in BE (#591)
AlexMIaoPU Oct 28, 2025
efbfdec
documentation fixes
KavikaPalletenne Oct 28, 2025
bf3534c
update authz for application reads
KavikaPalletenne Oct 28, 2025
2bc7913
only show answers/questions for submitted applications
KavikaPalletenne Oct 28, 2025
9ae7ca1
fix sql `==` check
KavikaPalletenne Oct 28, 2025
d5ceff4
Progress on campaign redesign, (#594)
RyanTan182 Nov 11, 2025
0bca489
Fixed Migration Error (#596)
RyanTan182 Nov 11, 2025
a1c9f20
fixed migration :(((( (
RyanTan182 Nov 11, 2025
a3ec550
initial nextjs setup
KavikaPalletenne Nov 13, 2025
caac3ef
basic dashboard organisation fetching
KavikaPalletenne Nov 29, 2025
68514c9
dashboard campaign details
KavikaPalletenne Nov 29, 2025
6bb71c4
application rating ui
KavikaPalletenne Nov 29, 2025
d613d3f
add buttons for publish & edit campaign questions
KavikaPalletenne Dec 2, 2025
323890c
Email templates UI (#608)
KavikaPalletenne Dec 3, 2025
d4733b1
Update .gitignore
KavikaPalletenne Dec 3, 2025
532e89d
fix: fixed some CN translations (#614)
AlexMIaoPU Dec 4, 2025
d3e5c79
Created campaign webpage utilising CampaignDetails struct
drboom16 Dec 4, 2025
62a7b31
Edit Campaign View (#610)
gyoumi Dec 8, 2025
9eda5a2
Chaos 617 create campaign nextjs (#619)
RyanTan182 Dec 9, 2025
49a6808
CRUD UI for organisation members (#612)
KavikaPalletenne Dec 9, 2025
2e84503
Chaos 616 campaign info page (#623)
drboom16 Dec 10, 2025
c575612
yarn -> bun migration
gyoumi Oct 10, 2025
992a84f
Chaos 577 create campaign be fe (#581)
Plebbaroni Oct 23, 2025
5a3a29e
fix spelling
KavikaPalletenne Oct 23, 2025
39cab2a
feat: added published flag to campaign (#589)
AlexMIaoPU Oct 28, 2025
e52c2af
588 fe dev only buttons for login + Added get_all orgs in BE (#591)
AlexMIaoPU Oct 28, 2025
f8a22a4
documentation fixes
KavikaPalletenne Oct 28, 2025
bc0b319
update authz for application reads
KavikaPalletenne Oct 28, 2025
972cab0
only show answers/questions for submitted applications
KavikaPalletenne Oct 28, 2025
2216db0
fix sql `==` check
KavikaPalletenne Oct 28, 2025
eedfa70
Progress on campaign redesign, (#594)
RyanTan182 Nov 11, 2025
e703f5e
Fixed Migration Error (#596)
RyanTan182 Nov 11, 2025
5e178ea
fixed migration :(((( (
RyanTan182 Nov 11, 2025
f2bdd2a
user names are defaulted to 'user' and have default profile icon (#601)
reganbenedetti Nov 21, 2025
fce6403
Chaos 584 integrate be fe adminmemberfunc (#593)
Plebbaroni Nov 21, 2025
5e20dbe
run rust build workflow on pulls to `CHAOS-571-integrate-be-fe`
KavikaPalletenne Nov 23, 2025
8246311
fix seeder organisation admin overwrite
KavikaPalletenne Dec 11, 2025
fd0e244
update backend readme to reflect seeder email arg
KavikaPalletenne Dec 12, 2025
d0e720c
additional backend setup steps
KavikaPalletenne Dec 12, 2025
f963fc4
nextjs handle `to` param in `/login`
KavikaPalletenne Dec 18, 2025
9d9f2ca
Campaign attachments (#631)
drboom16 Dec 24, 2025
89b7711
Application rating summary (#632)
A2H4D Dec 28, 2025
12b702f
Campaign question management page (#644)
KavikaPalletenne Jan 10, 2026
2c58dc0
Application answering page (#640)
Plebbaroni Jan 10, 2026
1574b2f
Staging deployment prep (#648)
Plebbaroni Jan 14, 2026
0ee5151
Merge branch 'CHAOS-571-integrate-be-fe' into CHAOS-598-nextjs
KavikaPalletenne Jan 14, 2026
88b3289
Update bun.lock
KavikaPalletenne Jan 14, 2026
812a492
fix backend import missing build errors
KavikaPalletenne Jan 14, 2026
2107c4e
fix opening tag for `StyledEngineProvider`
KavikaPalletenne Jan 14, 2026
28806e9
reinstate removed frontend api functions
KavikaPalletenne Jan 14, 2026
f6e1b94
Merge pull request #609 from devsoc-unsw/CHAOS-598-nextjs
KavikaPalletenne Jan 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
8 changes: 8 additions & 0 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
FROM mcr.microsoft.com/devcontainers/base:ubuntu

# Setup packages
RUN apt update && export DEBIAN_FRONTEND=noninteractive \
&& apt -y install --no-install-recommends libssl-dev pkgconf build-essential postgresql-client

# Note: Rust, Node.js, and Bun are installed via devcontainer.json features.
# sqlx-cli will be installed in post-create.sh to ensure it uses the correct cargo environment.
27 changes: 27 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"name": "Chaos Dev Container",
"dockerComposeFile": "docker-compose.yml",
"service": "app",
"workspaceFolder": "/workspaces/chaos",
"features": {
"ghcr.io/devcontainers/features/node:1": {
"version": "lts"
},
"ghcr.io/devcontainers/features/rust:1": {
"version": "latest"
},
"ghcr.io/michidk/devcontainers-features/bun:1": {
"version": "latest"
}
},
"customizations": {
"vscode": {
"extensions": [
"rust-lang.rust-analyzer",
"DBCode.dbcode"
]
}
},
"postCreateCommand": "bash .devcontainer/post-create.sh",
"remoteUser": "vscode"
}
29 changes: 29 additions & 0 deletions .devcontainer/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
services:
app:
build:
context: .
dockerfile: Dockerfile
volumes:
- ..:/workspaces/chaos:cached
# Overrides default command so things don't shut down after the process ends.
command: sleep infinity
# Use the same network as the db service to access it via localhost
network_mode: service:db

db:
image: postgres:17
restart: unless-stopped
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: password
POSTGRES_DB: chaos
volumes:
- chaos-postgres-data:/var/lib/postgresql/data
# Forward ports: 5432 (db), 3000 (frontend), 8080 (backend)
ports:
- "5433:5432"
- "3000:3000"
- "8080:8080"

volumes:
chaos-postgres-data:
46 changes: 46 additions & 0 deletions .devcontainer/post-create.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/bin/bash
set -e

echo "Starting post-create setup..."

# Create backend/.env
echo "Creating backend/.env..."
cat << 'EOF' > backend/.env
DATABASE_URL="postgres://postgres:password@localhost:5432/chaos"
JWT_SECRET="test_secret"
GOOGLE_CLIENT_ID="test"
GOOGLE_CLIENT_SECRET="test"
GOOGLE_REDIRECT_URI="http://localhost:3000/auth/callback"
S3_BUCKET_NAME="chaos-storage"
S3_ACCESS_KEY="test_access_key"
S3_SECRET_KEY="test_secret_key"
S3_ENDPOINT="https://chaos-storage.s3.ap-southeast-1.amazonaws.com"
S3_REGION_NAME="ap-southeast-1"
DEV_ENV="dev"
SMTP_USERNAME="test_username"
SMTP_PASSWORD="test_password"
SMTP_HOST="smtp.example.com"
EOF

# Install sqlx-cli if not present
if ! command -V sqlx &> /dev/null; then
echo "Installing sqlx-cli..."
cargo install sqlx-cli --no-default-features --features native-tls,postgres
fi

# Wait for Postgres
echo "Waiting for Postgres..."
until PGPASSWORD=password psql -h "db" -U "postgres" -d "chaos" -c '\q' 2>/dev/null; do
echo "Waiting for postgres at db:5432..."
sleep 2
done

# Setup DB
echo "Setting up database..."
cd backend

# Create database if not exists
sqlx database create || true
sqlx migrate run

echo "Setup complete!"
9 changes: 9 additions & 0 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,15 @@ jobs:
name: Build (Backend)
runs-on: ubuntu-latest
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
services:
postgres:
image: postgres:16
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: password
POSTGRES_DB: chaos
ports:
- 5432:5432
steps:
- uses: actions/checkout@v4
with:
Expand Down
38 changes: 38 additions & 0 deletions .github/workflows/frontend-nextjs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: Frontend (Next.js)

on:
pull_request:
branches: [main, "renovate/*", "CHAOS-224-KHAOS-rewrite", "CHAOS-571-integrate-be-fe", "CHAOS-598-nextjs"]
paths:
- "frontend-nextjs/**"
- ".github/workflows/frontend-nextjs.yml"
push:
branches: ["renovate/*"]
paths:
- "frontend-nextjs/**"
- ".github/workflows/frontend-nextjs.yml"

jobs:
build:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./frontend-nextjs

steps:
- uses: actions/checkout@v4

- name: Setup Bun
uses: oven-sh/setup-bun@v1
with:
bun-version: latest

- name: Install dependencies
run: bun install

- name: Build
run: bun run build
env:
NEXT_PUBLIC_APP_URL: http://localhost:3000
NEXT_OAUTH_CALLBACK_URL: http://localhost:8080/auth/google
NEXT_API_BASE_URL: https://localhost:8080
16 changes: 14 additions & 2 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,15 @@ name: Rust

on:
pull_request:
branches: [main, "renovate/*", "CHAOS-224-KHAOS-rewrite"]
branches: [main, "renovate/*", "CHAOS-224-KHAOS-rewrite", "CHAOS-571-integrate-be-fe", "CHAOS-598-nextjs"]
paths:
- "backend/**"
- ".github/workflows/rust.yml"
push:
branches: ["renovate/*"]
paths:
- "backend/**"
- ".github/workflows/rust.yml"

env:
CARGO_TERM_COLOR: always
Expand Down Expand Up @@ -39,6 +45,12 @@ jobs:
echo "SMTP_USERNAME=test_username" >> backend/.env
echo "SMTP_PASSWORD=test_password" >> backend/.env
echo "SMTP_HOST=smtp.example.com" >> backend/.env
echo "CAMPAIGN_NAME_MAX_CHARS=50" >> backend/.env
echo "CAMPAIGN_DESCRIPTION_MAX_ChARS=500" >> backend/.env
echo "ROLE_NAME_MAX_CHARS=20" >> backend/.env
echo "ROLE_DESCRIPTION_MAX_CHARS=50" >> backend/.env
echo "ROLE_POSITIONS_AVAILABLE_MAX=20" >> backend/.env
echo "CHAOS_SUPER_USER_EMAIL=me@example.com" >> backend/.env
# selecting a toolchain either by action or manual `rustup` calls should happen
# before the plugin, as it uses the current rustc version as its cache key
- uses: actions-rs/toolchain@v1
Expand Down Expand Up @@ -69,4 +81,4 @@ jobs:
working-directory: backend/database-seeding
run: |
cargo build
cargo run
cargo run -- --email me@example.com
7 changes: 6 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
**/.DS_Store
**/.DS_Store
**/.vscode/
**/.idea/
**/.next/
**/target/
**/.env.*
157 changes: 157 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
# Agent Guidelines for Chaos Repository

## Build/Lint/Test Commands

### Frontend (React/TypeScript)
- **Start dev server**: `cd frontend && yarn start`
- **Build**: `cd frontend && yarn build`
- **Lint**: `cd frontend && yarn lint`
- **Lint fix**: `cd frontend && yarn lint:fix`
- **Format**: `cd frontend && yarn format`
- **Type check**: `cd frontend && npx tsc --noEmit`

### Backend (Rust)
- **Build**: `cd backend/server && cargo build`
- **Run**: `cd backend/server && cargo run`
- **Format**: `cd backend/server && cargo fmt`
- **Check**: `cd backend/server && cargo check`
- **Test**: `cd backend/server && cargo test`

### Database
- **Run migrations**: Run `sqlx migrate run` in `backend` directory
- **Create new migrations**: Run `sqlx migrate add <name>` e.g. `sqlx migrate add user_settings` in `backend` directory. This will create a file of the format `<time>_name.sql` in `backend/migrations` directory

## Architecture Overview

### Backend (Rust/Axum)
The backend follows a clean architecture pattern with three main layers:

**Handler Layer** (`backend/server/src/handler/`):
- Contains HTTP request handlers organized by domain (user, application, campaign, etc.)
- Each handler module contains structs with methods that process HTTP requests
- Handlers extract data from requests, call service layer methods, and return responses
- All handler functions must be documented with `///` comments explaining purpose, parameters, and return values
- Example: `UserHandler` has methods like `get()`, `update_name()`, `update_pronouns()`

**Service Layer** (`backend/server/src/service/`):
- Contains business logic and database operations
- Each service module handles the core functionality for its domain
- Services interact directly with the database using SQLx
- All service functions must be documented with `///` comments
- **Database Optimization**: Minimize DB queries per function to reduce round trips
- **Complex Queries**: Use large SQL queries with nested one-to-many objects as vectors of `sqlx::Json`
- Includes authentication (JWT, OAuth2), email handling, and file storage

**Model Layer** (`backend/server/src/models/`):
- Contains data structures and database interaction logic
- Each model represents a database entity with serialization/deserialization
- Models use SQLx traits like `FromRow` for database mapping
- All structs and their fields must be documented with `///` comments
- Includes error types, authentication structs, and utility types

**Key Patterns**:
- Database transactions are handled via `DBTransaction` wrapper
- Authentication uses JWT tokens with Google OAuth2 integration
- File storage uses S3-compatible services
- Email functionality via Lettre library
- ID generation using Snowflake algorithm
- **Database Query Optimization**: Minimize DB round trips by using complex queries with nested data:
```sql
-- Example: Get campaign with all roles and questions in one query
SELECT
campaigns.*,
COALESCE(json_agg(DISTINCT roles.*) FILTER (WHERE roles.id IS NOT NULL), '[]') as roles,
COALESCE(json_agg(DISTINCT questions.*) FILTER (WHERE questions.id IS NOT NULL), '[]') as questions
FROM campaigns
LEFT JOIN roles ON roles.campaign_id = campaigns.id
LEFT JOIN questions ON questions.campaign_id = campaigns.id
WHERE campaigns.id = $1
GROUP BY campaigns.id
```
- **i64 ID Serialization**: All i64 IDs must use `#[serde(serialize_with = "crate::models::serde_string::serialize")]` and `#[serde(deserialize_with = "crate::models::serde_string::deserialize")]` to convert between i64 and string representations for JavaScript compatibility
- **API Documentation**: All handler endpoints must be documented in `backend/api.yaml` with:
- `operationId`: Unique identifier for the operation
- `description`: Clear description of what the endpoint does
- `tags`: Appropriate categorization (e.g., "User", "Auth", "Campaign")
- Request/response schemas with examples
- Error response definitions

### Frontend (React/TypeScript)
The frontend follows a component-based architecture with clear separation of concerns:

**Component Structure** (`frontend/src/components/`):
- Reusable UI components organized by feature (AdminSideBar, CampaignCard, etc.)
- Styled using twin.macro (Tailwind CSS + Emotion)
- Components use TypeScript with strict typing
- Follows atomic design principles with ui/ folder for base components

**Page Structure** (`frontend/src/pages/`):
- Route-based page components with lazy loading
- Organized by feature areas (admin, application_page, dashboard, etc.)
- Each page handles its own state management and API calls

**Context Management** (`frontend/src/contexts/`):
- React contexts for global state (UserContext, MessagePopupContext)
- Centralized state management for user authentication and UI state

**API Layer** (`frontend/src/api/`):
- Centralized API client using fetch with custom error handling
- Handles large integer serialization to avoid JavaScript precision issues
- Cookie-based authentication with backend
- **Large Integer Processing**: Automatically converts i64 IDs from strings to preserve precision:
```typescript
// Regex-based processing in API client converts large integers to strings
const processedText = text.replace(/"id":(\d{16,})/g, '"id":"$1"')
```

**Key Patterns**:
- Custom hooks for data fetching and state management
- Toast notifications for user feedback
- Form handling with react-hook-form and Zod validation
- Responsive design with Tailwind CSS
- Component composition over inheritance

## Code Style Guidelines

### TypeScript/React (Frontend)
- **Imports**: Group by builtin → external → internal → parent → sibling → index → object → type. Alphabetize within groups.
- **Naming**: camelCase for variables/functions, PascalCase for types/components, UPPER_CASE for constants
- **Types**: Strict TypeScript with `strict: true`, consistent type imports (`import type`)
- **Components**: Arrow function components, .tsx/.ts extensions only
- **Formatting**: Prettier with 2-space indentation, 80 char width, double quotes, semicolons
- **Linting**: Airbnb + TypeScript rules, no console logs in production
- **ID Field Types**: All ID fields must be `string` type to handle i64 integers from backend:
```typescript
export type User = {
id: string; // Not number - handles large i64 values
campaign_id: string;
organisation_id: string;
// ... other fields
}
```

### Rust (Backend)
- **Formatting**: Standard rustfmt (enforced by pre-commit)
- **Naming**: Standard Rust conventions (snake_case for functions/variables, PascalCase for types)
- **Error handling**: Use `anyhow` and `thiserror` for consistent error types
- **Async**: Use `tokio` runtime with async/await patterns
- **Documentation**: All functions and structs must be documented with `///` comments
- **API Documentation**: All new handler functions must be documented in `backend/api.yaml` using OpenAPI 3.0.0 specification
- **Database Optimization**: Minimize DB queries per function to reduce round trips:
- Use complex SQL queries with JOINs and aggregations
- Return nested one-to-many relationships as `Vec<sqlx::Json<T>>`
- Prefer single queries over multiple round trips when possible
- **i64 ID Handling**: All i64 IDs must be serialized as strings for JavaScript compatibility:
```rust
#[serde(serialize_with = "crate::models::serde_string::serialize")]
#[serde(deserialize_with = "crate::models::serde_string::deserialize")]
pub id: i64,
```
- Use the existing `serde_string` module functions for serialization
- Frontend TypeScript types must use `string` type for all ID fields
- This prevents JavaScript Number precision issues with large integers

### General
- **Pre-commit**: Run `pre-commit install` to enable automatic formatting/linting
- **No unused vars**: Prefix with `_` to ignore, or remove if truly unused
- **Security**: Never commit secrets, use environment variables via `.env` files
Loading
Loading