diff --git a/README.md b/README.md index 4050eb53..c09d2c93 100644 --- a/README.md +++ b/README.md @@ -1,85 +1,164 @@ -![Banner](https://github.com/user-attachments/assets/84169d26-84f0-4786-bf37-87484ef475bb) +[![Banner](https://github.com/user-attachments/assets/84169d26-84f0-4786-bf37-87484ef475bb)](https://gitmarks.org) -# GitMarks -GitMarks is a Git-based grading platform designed to mirror industry standard workflows and provide support for both students and teaching staff. +## GitMarks Overview -*Developed in 2024 by:* +GitMarks is a Git-based grading platform that streamlines the academic assessment process by leveraging industry-standard workflows. It provides a comprehensive solution for both educational staff and students, combining automated grading capabilities with professional development practices. -- [Alex Angione](https://github.com/alexangione419) -- [Cam Plume](https://github.com/CamPlume1) -- [Kenny Chen](https://github.com/kennybc) -- [Nandini Ghosh](https://github.com/nandini-ghosh) -- [Nick Tietje](https://github.com/ntietje1) -- [Seby Tremblay](https://github.com/sebytremblay) - -## Tech Stack +## Technology Stack +### Core Technologies [![Go](https://img.shields.io/badge/go-%2300ADD8.svg?style=for-the-badge&logo=go&logoColor=white)](https://go.dev/doc/) +[![Go Fiber](https://img.shields.io/badge/go--fiber-0096C2?style=for-the-badge&logo=go&logoColor=white)](https://gofiber.io/) [![TypeScript](https://img.shields.io/badge/typescript-%23007ACC.svg?style=for-the-badge&logo=typescript&logoColor=white)](https://www.typescriptlang.org/) [![React](https://camo.githubusercontent.com/3467eb8e0dc6bdaa8fa6e979185d371ab39c105ec7bd6a01048806b74378d24c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f52656163742d3230323332413f7374796c653d666f722d7468652d6261646765266c6f676f3d7265616374266c6f676f436f6c6f723d363144414642)](https://react.dev/) +[![GitHub](https://img.shields.io/badge/github-%23121011.svg?style=for-the-badge&logo=github&logoColor=white)](https://github.com) +[![React Query](https://img.shields.io/badge/-React%20Query-FF4154?style=for-the-badge&logo=react%20query&logoColor=white)](https://tanstack.com/query/v5) +[![Chart JS](https://img.shields.io/badge/Chart%20js-FF6384?style=for-the-badge&logo=chartdotjs&logoColor=white)](https://www.chartjs.org/) +[![Postgres](https://img.shields.io/badge/postgres-%23316192.svg?style=for-the-badge&logo=postgresql&logoColor=white)](https://www.postgresql.org/) -## Tools - +### Infrastructure [![Docker](https://img.shields.io/badge/docker-%230db7ed.svg?style=for-the-badge&logo=docker&logoColor=white)](https://www.docker.com/) +[![Kubernetes](https://img.shields.io/badge/kubernetes-3970e4?style=for-the-badge&logo=kubernetes&logoColor=white)](https://www.kubernetes.io/) +[![Amazon S3](https://img.shields.io/badge/Amazon%20S3-2ca02c?style=for-the-badge&logo=amazons3&logoColor=white)](https://aws.amazon.com/s3/) +[![ECS](https://img.shields.io/badge/Amazon%20ECS-FF9900?style=for-the-badge&logo=amazonecs&logoColor=white)](https://aws.amazon.com/ecs/) +[![RDS](https://img.shields.io/badge/Amazon%20RDS-1f77b4?style=for-the-badge&logo=amazonrds&logoColor=white)](https://aws.amazon.com/rds/) + +## Features + +
+ +| Category | Capabilities | +|:---------|:-------------| +| **GitHub Integration** | • Seamless repository management
• Native pull request workflow
• Automated assignment distribution | +| **Automated Assessment** | • GitHub Actions integration
• Customizable test suites
• Immediate feedback loops | +| **Code Review System** | • Line-by-line annotations
• Inline feedback tools
• Review history tracking | +| **Assignment Management** | • Template-based distribution
• Deadline management
• Bulk operations support | +| **Progress Analytics** | • Real-time submission tracking
• Performance metrics
• Completion statistics | + +
+ +## Team + +
+ + + + + + + + + + + + +
+ +
+ Nick Tietje
+
+ Full Stack Developer +
+ +
+ Cam Plume
+
+ Backend Developer +
+ +
+ Kenny Chen
+
+ Full Stack Developer +
+ +
+ Nandini Ghosh
+
+ Designer & Frontend Developer +
+ +
+ Alex Angione
+
+ Full Stack Developer +
+ +
+ Seby Tremblay
+
+ Infrastructure & Product Manager +
+ +
+ +## Getting Started + +### Prerequisites + +The following tools are required to run GitMarks: + +- [Go](https://go.dev/doc/install) - Backend runtime +- [Node.js and npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) - Frontend development +- [Docker](https://www.docker.com/get-started/) and [Docker Desktop](https://www.docker.com/products/docker-desktop/) - Database containerization +- [Ngrok](https://ngrok.com/docs/getting-started/) - Local development tunneling + +### Configuration + +1. Backend Configuration (`/backend/.env`): +```env +APP_PRIVATE_KEY= +APP_ID= +APP_INSTALLATION_ID= +APP_WEBHOOK_SECRET= +APP_NAME= +CLIENT_REDIRECT_URL= +CLIENT_ID= +CLIENT_SECRET= +CLIENT_URL= +CLIENT_TOKEN_URL= +CLIENT_JWT_SECRET= +DATABASE_URL= +``` -## Development Enviroment Setup - -Please install the following software - -[Go](https://go.dev/doc/install) our primary backend language. - -[Node Package Manager](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) -our package manager in the frontend. - -[Docker](https://www.docker.com/get-started/) and -[Docker Desktop](https://www.docker.com/products/docker-desktop/) our Postgres -Database will be containerized in Docker. - -[Ngrok](https://ngrok.com/docs/getting-started/) Allows us to easily connect the -frontend to backend code. Make an account for a stable link! +2. Frontend Configuration (`/frontend/.env`): +```env +VITE_PUBLIC_API_DOMAIN= +VITE_PUBLIC_FRONTEND_DOMAIN= +VITE_GITHUB_CLIENT_ID= +VITE_GITHUB_APP_NAME= +``` -## Before Running +### Development Setup -Create an .env file in the backend directory: +#### Using Make (Recommended) +```bash +# 1. Start the database +make db-run -``` -APP_PRIVATE_KEY= -APP_ID= -APP_INSTALLATION_ID= -APP_WEBHOOK_SECRET= -APP_NAME= -CLIENT_REDIRECT_URL= -CLIENT_ID= -CLIENT_SECRET= -CLIENT_URL= -CLIENT_TOKEN_URL= -CLIENT_JWT_SECRET= -DATABASE_URL= -``` +# 2. Launch the backend +make backend-dep +make backend-run -Create a second .env file in the frontend root directory: +# 3. Start ngrok tunnel +make ngrok-run +# 4. Launch the frontend +make frontend-run ``` -VITE_PUBLIC_API_DOMAIN= -VITE_PUBLIC_FRONTEND_DOMAIN= -VITE_GITHUB_CLIENT_ID= -VITE_GITHUB_APP_NAME= -``` - -## Running The Project in A Dev Environment -1. Launch Docker Desktop -2. In the base of the repo: run `make db-run` -3. Then, open a new tab to run commands in: run `make backend-dep` then `make backend-run` -4. Next, in a new tab run `make ngrok-run` -5. Finally, open one last new tab: run `make frontend-run` +#### Manual Setup +```bash +# 1. Start Docker services +docker compose up --build +# 2. Start ngrok tunnel +ngrok http --domain={your-ngrok-domain} 8080 -## Running locally in dev mode without using Make (due to multi-line env variable issues): +# 3. Install frontend dependencies +cd frontend +npm install -1. Launch Docker Desktop -2. In the repo root: run `docker compose up --build` -3. In a new terminal: run `ngrok http --domain={} 8080` -4. In a new terminal: run `cd frontend` -5. (On first run) In the frontend directory: run `npm i` -6. In the frontend directory: run `npm run dev` +# 4. Start frontend development server +npm run dev +``` diff --git a/frontend/public/images/alexander-angione.jpg b/frontend/public/images/alexander-angione.jpg new file mode 100644 index 00000000..eac12aca Binary files /dev/null and b/frontend/public/images/alexander-angione.jpg differ diff --git a/frontend/public/images/cameron-plume.jpg b/frontend/public/images/cameron-plume.jpg new file mode 100644 index 00000000..893710b1 Binary files /dev/null and b/frontend/public/images/cameron-plume.jpg differ diff --git a/frontend/public/images/kenneth-chen.png b/frontend/public/images/kenneth-chen.png new file mode 100644 index 00000000..353bf629 Binary files /dev/null and b/frontend/public/images/kenneth-chen.png differ diff --git a/frontend/public/images/nandini-ghosh.png b/frontend/public/images/nandini-ghosh.png new file mode 100644 index 00000000..bed82cf1 Binary files /dev/null and b/frontend/public/images/nandini-ghosh.png differ diff --git a/frontend/public/images/nick-tietje.jpg b/frontend/public/images/nick-tietje.jpg new file mode 100644 index 00000000..65e6cf62 Binary files /dev/null and b/frontend/public/images/nick-tietje.jpg differ diff --git a/frontend/public/images/sebastian-tremblay.png b/frontend/public/images/sebastian-tremblay.png new file mode 100644 index 00000000..087d4cd2 Binary files /dev/null and b/frontend/public/images/sebastian-tremblay.png differ diff --git a/frontend/public/images/team-photo.jpg b/frontend/public/images/team-photo.jpg new file mode 100644 index 00000000..f48e6b40 Binary files /dev/null and b/frontend/public/images/team-photo.jpg differ diff --git a/frontend/src/components/Layout/index.tsx b/frontend/src/components/Layout/index.tsx index ef79fc63..aded3d1a 100644 --- a/frontend/src/components/Layout/index.tsx +++ b/frontend/src/components/Layout/index.tsx @@ -11,7 +11,7 @@ import LeftNav from "./LeftNav"; import TopNav from "./TopNav"; import "./styles.css"; -import { FaTachometerAlt } from "react-icons/fa"; +import { FaInfoCircle, FaTachometerAlt } from "react-icons/fa"; import { MdEditDocument } from "react-icons/md"; import { MdFactCheck } from "react-icons/md"; import { FaGear } from "react-icons/fa6"; @@ -52,7 +52,8 @@ const Layout: React.FC = () => { ...(classroomUser?.classroom_role === ClassroomRole.PROFESSOR ? professorNavItems : []), - { name: "Settings", dest: "/app/settings", Icon: FaGear } + { name: "Settings", dest: "/app/settings", Icon: FaGear }, + { name: "About Us", dest: "/app/about-us", Icon: FaInfoCircle } ]; if (loadingCurrentClassroomUser) { diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx index 59021490..30f9e7cc 100644 --- a/frontend/src/main.tsx +++ b/frontend/src/main.tsx @@ -78,6 +78,7 @@ export default function App(): React.JSX.Element { {/******* CLASS SELECTED: INNER APP *******/} }> + } /> } /> = ({ name, title, imageUrl, bio, website }) => { + return ( + +
+ {`${name}`} +
+
+

{name}

+

{title}

+

{bio}

+
+
+ ); + }; + + +const AboutUs: React.FC = () => { + const team = [ + { + name: "Nicholas Tietje", + title: "Full Stack Developer", + imageUrl: "/images/nick-tietje.jpg", + bio: "Nick is passionate about creating intuitive and engaging web and mobile experiences. Former Database Design TA, Boardgame enjoyer, Kotlin connoisseur", + website: "https://nicktietje.com" + }, + { + name: "Cameron Plume", + title: "Backend Developer", + imageUrl: "/images/cameron-plume.jpg", + bio: "Former OOD TA, CS 1200 course author. Heavily involved with Generate Product Development. Golang advocate, Systems nerd, Ski bum. ", + website: "https://cameron-plume.netlify.app/" + }, + { + name: "Nandini Ghosh", + title: "Designer & Frontend Developer", + imageUrl: "/images/nandini-ghosh.png", + bio: "Nandini is a frontend developer and a UI/UX designer who loves bridging technology and human-centered design. President of NU Women in Tech, she loves cats, drinking tea and learning new recipes.", + website: "https://www.nandinighosh.com/" + }, + { + name: "Alexander Angione", + title: "Full Stack Developer", + imageUrl: "/images/alexander-angione.jpg", + bio: "Alex is an embedded, iOS, and full-stack software engineer with a desire to learn as much as possible. He's a former OOD/Fundies 2 TA and Oasis mentor, a basketball and volleyball enjoyer, and a cheese enthusiast", + website: "https://github.com/alexangione419" + }, + { + name: "Sebastian Tremblay", + title: "Infrastructure & Product Manager", + imageUrl: "/images/sebastian-tremblay.png", + bio: "Seby is an aspiring backend engineer interested in systems and large language models. He enjoys teaching, skating, and, of course, Panera.", + website: "https://sebytremblay.com/" + }, + { + name: "Kenneth Chen", + title: "Full Stack Developer", + imageUrl: "/images/kenneth-chen.png", + bio: "Kenny likes coding and code architecting. Founding president of Cooking Club, love art, cooking, and volleyball. Big braised ribs fan", + website: "https://www.kenny.us/" + } + ]; + + return ( +
+
+

About GitMarks

+

{"\"Built by TAs, for TAs\""}

+
+

+ {"GitMarks is an innovative grading application designed to bridge the gap between academic programming assignments and industry practices. By leveraging GitHub's infrastructure, GitMarks creates a seamless experience for students to submit assignments through pull requests while allowing teaching assistants to provide detailed feedback through code reviews."} +

+

+ {"Our platform helps students familiarize themselves with industry-standard tools and workflows while making the grading process more efficient for course staff. With features like automated repository management, inline feedback, and comprehensive analytics, GitMarks transforms the way programming assignments are handled in academic settings."} +

+
+
+

Industry-Aligned

+

{"Uses real-world development workflows with Git and GitHub"}

+
+
+

Seamless Experience

+

{"Streamlined submission and feedback process for students and TAs"}

+
+
+

Built for Scale

+

{"Designed to handle large course sizes with efficient grading workflows"}

+
+
+

In-Depth Analytics

+

{"Comprehensive analytics to track student progress and submission patterns"}

+
+
+ + + + + View on GitHub + +
+ +

Our Team

+
+ {team.map((member) => ( + + ))} +
+
+ The GitMarks Team +
+
+
+ ); +}; + +export default AboutUs; diff --git a/frontend/src/pages/AboutUs/styles.css b/frontend/src/pages/AboutUs/styles.css new file mode 100644 index 00000000..df31c374 --- /dev/null +++ b/frontend/src/pages/AboutUs/styles.css @@ -0,0 +1,203 @@ +.AboutUs { + padding: 60px 0; + min-height: calc(100vh); +} + +.AboutUs__container { + max-width: 1200px; + margin: 0 auto; + padding: 0 20px; +} + +.AboutUs__title { + text-align: center; + font-family: var(--primary-font); + font-size: 48px; + font-weight: 700; + margin-bottom: 40px; + color: var(--primary-text); +} + +.AboutUs__title + .AboutUs__subtitle { + margin-top: -30px; +} + +.AboutUs__grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); + gap: 40px; + justify-items: center; + margin-bottom: 60px; +} + +.AboutCard { + width: 300px; + background: var(--brand-gradient-light); + border-radius: 8px; + overflow: hidden; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); + transition: all 0.3s ease; + height: auto; + position: relative; +} + +.AboutCard:hover { + transform: translateY(-8px); + box-shadow: 0 8px 16px rgba(0, 0, 0, 0.15); +} + +.AboutCard__image { + width: 100%; + height: 280px; + overflow: hidden; + position: relative; +} + +.AboutCard__image img { + width: 100%; + height: 100%; + object-fit: cover; + transition: transform 0.3s ease; +} + +.AboutCard:hover .AboutCard__image img { + transform: scale(1.02); +} + +.AboutCard__info { + padding: 20px; + text-align: center; +} + +.AboutCard__name { + font-family: var(--primary-font); + font-weight: 500; + font-size: 18px; + margin: 0 0 4px 0; + color: var(--primary-text); +} + +.AboutCard__title { + font-family: var(--primary-font); + font-size: 14px; + color: var(--secondary-text); + margin: 0; +} + +.AboutCard__bio { + font-family: var(--primary-font); + font-size: 14px; + line-height: 1.5; + color: var(--secondary-text); + margin: 12px 0 0 0; + text-align: left; +} + +.AboutUs__team-photo { + width: 100%; + max-width: 900px; + margin: 0 auto 60px; + border-radius: 12px; + overflow: hidden; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); +} + +.AboutUs__team-photo img { + width: 100%; + height: auto; + display: block; +} + +.AboutUs__description { + max-width: 800px; + margin: 0 auto 60px; + text-align: center; +} + +.AboutUs__description p { + font-family: var(--primary-font); + font-size: 16px; + line-height: 1.6; + color: var(--secondary-text); + margin-bottom: 24px; +} + +.AboutUs__features { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + gap: 30px; + margin-top: 40px; + padding-bottom: 30px; +} + +.AboutUs__feature { + padding: 24px; + background: var(--brand-gradient-light); + border-radius: 8px; + text-align: center; + transition: all 0.3s ease; + cursor: pointer; + border: 1px solid transparent; +} + +.AboutUs__feature:hover { + transform: translateY(-3px); + box-shadow: 0 6px 12px rgba(0, 0, 0, 0.1); + border-color: var(--brand-lightest); +} + +.AboutUs__feature h3 { + font-family: var(--primary-font); + font-size: 20px; + color: var(--primary-text); + margin-bottom: 12px; + transition: color 0.3s ease; +} + +.AboutUs__feature:hover h3 { + color: var(--accent-color, #007bff); +} + +.AboutUs__feature p { + font-family: var(--primary-font); + font-size: 14px; + color: var(--secondary-text); + margin: 0; +} + +.AboutUs__subtitle { + text-align: center; + font-family: var(--primary-font); + font-size: 20px; + font-weight: 500; + margin-bottom: 30px; + color: var(--caption-text); +} + +.AboutUs__github-button { + display: inline-flex; + align-items: center; + justify-content: center; + gap: 8px; + margin: 0 auto 60px; + cursor: pointer; + text-decoration: none; + transition: opacity 0.3s ease; +} + +.AboutUs__github-button:hover { + opacity: 0.8; +} + +.AboutUs__github-button svg { + width: 20px; + height: 20px; + fill: var(--primary-text); +} + +.AboutUs__github-button span { + font-family: var(--primary-font); + font-size: 16px; + color: var(--primary-text); + text-decoration: underline; +} diff --git a/frontend/src/pages/index.tsx b/frontend/src/pages/index.tsx index 1e837515..9932c007 100644 --- a/frontend/src/pages/index.tsx +++ b/frontend/src/pages/index.tsx @@ -25,6 +25,8 @@ import InviteStudents from "./Classrooms/InviteStudents"; import Success from "./Classrooms/Sucess"; import Landing from "./Classrooms/Landing"; import AccessDenied from "./AccessDenied"; +import AboutUs from "./AboutUs"; + export { PageNotFound, Settings, @@ -53,4 +55,5 @@ export { Success, Landing, AccessDenied, + AboutUs, };