Skip to content

Commit

Permalink
Merge pull request #70 from brendantwh/final
Browse files Browse the repository at this point in the history
Synced timers, date sort on question history
  • Loading branch information
brendantwh authored Nov 13, 2024
2 parents fa3e2d7 + f7cabe1 commit 647baa5
Show file tree
Hide file tree
Showing 15 changed files with 256 additions and 121 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
node_modules/
docker-compose.prod*
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ and access PeerPrep at [localhost:3000](http://localhost:3000), or the IP addres
#### Developing
If you are developing PeerPrep, you can use [Compose Watch](https://docs.docker.com/compose/how-tos/file-watch/) to automatically update and preview code changes:
```sh
docker compose up --watch --build
docker compose -f docker-compose.dev.yml up --watch --build
```

### API Endpoints
Expand Down
94 changes: 94 additions & 0 deletions docker-compose.dev.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# docker-compose for dev
version: '3.8'

services:
frontend:
build:
context: ./frontend
dockerfile: Dockerfile.dev
args:
PUBLIC_URL: ${PUBLIC_URL}
WS_PUBLIC_URL: ${WS_PUBLIC_URL}
FRONTEND_PORT: ${FRONTEND_PORT}
QUESTION_API_PORT: ${QUESTION_API_PORT}
USER_API_PORT: ${USER_API_PORT}
MATCHING_API_PORT: ${MATCHING_API_PORT}
COLLAB_API_PORT: ${COLLAB_API_PORT}
ports:
- "${FRONTEND_PORT}:${FRONTEND_PORT}"
develop:
watch:
- action: sync
path: ./frontend
target: /app

question:
build:
context: ./backend/question-service
dockerfile: Dockerfile.dev
ports:
- "${QUESTION_API_PORT}:2000"
develop:
watch:
- action: sync
path: ./backend/question-service
target: /app

user:
build:
context: ./backend/user-service
dockerfile: Dockerfile.prod
env_file:
- ./backend/user-service/.env
ports:
- "${USER_API_PORT}:3001"

zookeeper:
image: confluentinc/cp-zookeeper:7.7.1
environment:
ZOOKEEPER_CLIENT_PORT: 2181
ports:
- "2181:2181"
healthcheck:
test: [ "CMD", "echo", "ruok", "|", "nc", "localhost", "2181", "|", "grep", "imok" ]
interval: 10s
timeout: 5s
retries: 5

kafka:
image: confluentinc/cp-kafka:7.7.1
ports:
- "9092:9092"
environment:
KAFKA_BROKER_ID: 1
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9092
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
depends_on:
zookeeper:
condition: service_healthy
healthcheck:
test: [ "CMD", "nc", "-z", "localhost", "9092" ]
interval: 10s
timeout: 5s
retries: 10

matching-service:
build:
context: ./backend/matching-service
dockerfile: Dockerfile.match
environment:
KAFKA_BROKER: kafka:9092
ports:
- "${MATCHING_API_PORT}:3002"
depends_on:
kafka:
condition: service_healthy

collab-service:
build:
context: ./backend/collab-service
dockerfile: Dockerfile.dev
ports:
- "${COLLAB_API_PORT}:3003"
14 changes: 7 additions & 7 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
# docker-compose for dev
version: '3.8'

services:
frontend:
build:
context: ./frontend
dockerfile: Dockerfile.dev
dockerfile: Dockerfile.prod
args:
PUBLIC_URL: ${PUBLIC_URL}
WS_PUBLIC_URL: ${WS_PUBLIC_URL}
Expand All @@ -16,11 +15,11 @@ services:
COLLAB_API_PORT: ${COLLAB_API_PORT}
ports:
- "${FRONTEND_PORT}:${FRONTEND_PORT}"
develop:
watch:
- action: sync
path: ./frontend
target: /app
depends_on:
- question
- user
- matching-service
- collab-service

question:
build:
Expand Down Expand Up @@ -92,3 +91,4 @@ services:
dockerfile: Dockerfile.dev
ports:
- "${COLLAB_API_PORT}:3003"

2 changes: 0 additions & 2 deletions frontend/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,3 @@ yarn-error.log*
# typescript
*.tsbuildinfo
next-env.d.ts

Dockerfile.prod
54 changes: 54 additions & 0 deletions frontend/Dockerfile.prod
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
FROM node:22-alpine3.19 AS builder
WORKDIR /app

ARG PUBLIC_URL
ARG WS_PUBLIC_URL
ARG FRONTEND_PORT
ARG QUESTION_API_PORT
ARG USER_API_PORT
ARG MATCHING_API_PORT
ARG COLLAB_API_PORT

ENV PUBLIC_URL=${PUBLIC_URL}
ENV WS_PUBLIC_URL=${WS_PUBLIC_URL}

ENV FRONTEND_PORT=${FRONTEND_PORT}
ENV NEXT_PUBLIC_FRONTEND_URL=${PUBLIC_URL}:${FRONTEND_PORT}

ENV QUESTION_API_PORT=${QUESTION_API_PORT}
ENV NEXT_PUBLIC_QUESTION_API_BASE_URL=${PUBLIC_URL}:${QUESTION_API_PORT}/questions

ENV USER_API_PORT=${USER_API_PORT}
ENV USER_API_BASE_URL=${PUBLIC_URL}:${USER_API_PORT}
ENV NEXT_PUBLIC_USER_API_AUTH_URL=${USER_API_BASE_URL}/auth
ENV NEXT_PUBLIC_USER_API_USERS_URL=${USER_API_BASE_URL}/users
ENV NEXT_PUBLIC_USER_API_EMAIL_URL=${USER_API_BASE_URL}/email
ENV NEXT_PUBLIC_USER_API_HISTORY_URL=${USER_API_BASE_URL}/users/history

ENV MATCHING_API_PORT=${MATCHING_API_PORT}
ENV NEXT_PUBLIC_MATCHING_API_URL=${PUBLIC_URL}:${MATCHING_API_PORT}/matching

ENV COLLAB_API_PORT=${COLLAB_API_PORT}
ENV NEXT_PUBLIC_COLLAB_API_URL=${PUBLIC_URL}:${COLLAB_API_PORT}

COPY package.json package-lock.json ./
RUN npm ci
COPY . .
ENV NEXT_TELEMETRY_DISABLED=1
RUN npm run build


FROM node:22-alpine3.19 AS runner
WORKDIR /app

ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1

RUN mkdir .next
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
COPY --from=builder /app/public ./public

EXPOSE 3000

CMD ["node", "server.js"]
2 changes: 1 addition & 1 deletion frontend/app/(authenticated)/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export default function AuthenticatedLayout({

function logout() {
deleteAllCookies();
router.push('/');
window.location.href = '/';
}

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ function CodeViewerContent() {
<div className="flex gap-4 min-h-screen px-10 pt-24 pb-5 text-primary">
{/* Left Panel: Question Details */}
<ScrollArea className="w-1/2 p-6 border rounded-lg shadow bg-white">
<h3 className="text-2xl font-serif font-large tracking-tight">
<h3 className="text-2xl font-serif font-medium tracking-tight">
{questionDetails?.title || ""}
</h3>
<div className="flex items-center gap-10 mt-3">
Expand Down
99 changes: 16 additions & 83 deletions frontend/app/(authenticated)/profile/question-history/columns.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
"use client"

import { Badge, BadgeProps } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { HoverCard, HoverCardContent, HoverCardTrigger } from "@/components/ui/hover-card";
import { ColumnDef } from "@tanstack/react-table"
import { AlignLeft, ArrowUpDown, MoreHorizontal } from "lucide-react"
import { MoreHorizontal } from "lucide-react"
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
import Link from "next/link"
import { DataTableColumnHeader } from "../../question-repo/data-table-column-header";

export type QuestionHistory = {
id: number;
Expand All @@ -24,64 +24,22 @@ export const columns : ColumnDef<QuestionHistory>[]= [
accessorKey: "id",
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
ID
<ArrowUpDown className="ml-2 h-4 w-4" />
</Button>
<DataTableColumnHeader column={column} title="ID" className="max-w-[30px]" />
)
},
},
{
accessorKey: "title",
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
Title
<ArrowUpDown className="ml-2 h-4 w-4" />
</Button>
<DataTableColumnHeader column={column} title="Title" className="min-w-[10vw] w-[15vw]" />
)
},
cell: ({ row }) => {
return (
<HoverCard>
<HoverCardTrigger>
<div className="flex space-x-2">
<span className="font-medium cursor-help">
{row.getValue("title")}
</span>
</div>
</HoverCardTrigger>
<HoverCardContent className="rounded-xl">
<div className="flex flex-col">
<div className="flex items-center font-semibold mb-2">
<AlignLeft className="h-4 w-4 mr-2" />
<span>Description</span>
</div>
<div>
<p>{row.original.description}</p>
</div>
</div>
</HoverCardContent>
</HoverCard>
)
},
},
{
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
Categories
<ArrowUpDown className="ml-2 h-4 w-4" />
</Button>
<DataTableColumnHeader column={column} title="Categories" />
)
},
accessorKey: "categories",
Expand All @@ -96,21 +54,13 @@ export const columns : ColumnDef<QuestionHistory>[]= [
),
filterFn: (row, id, selectedCategories) => {
const rowCategories = row.getValue(id);
console.log(selectedCategories);
console.log(rowCategories);
return selectedCategories.every((category: string) => (rowCategories as string[]).includes(category));
},
},
{
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
Complexity
<ArrowUpDown className="ml-2 h-4 w-4" />
</Button>
<DataTableColumnHeader column={column} title="Complexity" />
)
},
accessorKey: "complexity",
Expand All @@ -128,13 +78,7 @@ export const columns : ColumnDef<QuestionHistory>[]= [
{
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
Number of Attempts
<ArrowUpDown className="ml-2 h-4 w-4" />
</Button>
<DataTableColumnHeader column={column} title="No. of Attempts" />
)
},
accessorKey: "attemptCount",
Expand All @@ -143,13 +87,7 @@ export const columns : ColumnDef<QuestionHistory>[]= [
{
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
Total Time Spent (mins)
<ArrowUpDown className="ml-2 h-4 w-4" />
</Button>
<DataTableColumnHeader column={column} title="Total Time Spent (mins)" />
)
},
accessorKey: "attemptTime",
Expand All @@ -159,28 +97,23 @@ export const columns : ColumnDef<QuestionHistory>[]= [
{
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
Last Attempted
<ArrowUpDown className="ml-2 h-4 w-4" />
</Button>
<DataTableColumnHeader column={column} title="Last Attempted" />
)
},
accessorKey: "attemptDate",
cell: ({ row }) => {
const attemptDate = row.original.attemptDate;
return new Date(attemptDate).toLocaleString("en-GB", {
day: "2-digit",
month: "2-digit",
day: "numeric",
month: "short",
year: "numeric",
hour: "2-digit",
hour: "numeric",
minute: "2-digit",
second: "2-digit",
hour12: false,
hour12: true,
});
},
sortingFn: "datetime",
sortDescFirst: true,
},
{
id: "actions",
Expand Down
Loading

0 comments on commit 647baa5

Please sign in to comment.