From 79328b4ccc7811c4e0ebc1e1556b4f678e1efdff Mon Sep 17 00:00:00 2001 From: Damian <37555910+DCRepublic@users.noreply.github.com> Date: Sun, 24 Nov 2024 18:29:35 -0500 Subject: [PATCH] Change branding to Planner/Plan --- .github/workflows/main.yml | 24 ++-- .gitlab-ci.yml | 4 +- README.md | 23 ++-- app/actions/getCourses.ts | 206 +++++++++++++++++------------- app/page.tsx | 74 ++--------- components/FullCourseList.tsx | 2 +- components/OLD.FullCourseList.tsx | 149 --------------------- components/PlanContext.tsx | 24 ++++ components/Search.tsx | 3 +- components/primitives.ts | 4 +- docker-compose.debug.yml | 11 +- docker-compose.yml | 40 +++--- package-lock.json | 4 +- package.json | 2 +- 14 files changed, 215 insertions(+), 355 deletions(-) delete mode 100644 components/OLD.FullCourseList.tsx create mode 100644 components/PlanContext.tsx diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 53515c3..ba402c2 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -4,21 +4,21 @@ name: Mirror on: push: - branches: [ "main" ] + branches: ["main"] jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - uses: action-pack/gitlab-sync@v3 - with: - # GitLab repo URL - url: https://gitlab.sccs.swarthmore.edu/sccs/scheduler.git - # GitLab username - username: mirrorbot - # GitLab token - token: ${{ secrets.GITLAB_TOKEN }} + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - uses: action-pack/gitlab-sync@v3 + with: + # GitLab repo URL + url: https://gitlab.sccs.swarthmore.edu/sccs/planner.git + # GitLab username + username: mirrorbot + # GitLab token + token: ${{ secrets.GITLAB_TOKEN }} diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index cc6cd89..1c314ca 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -21,11 +21,11 @@ build: stage: build script: - docker compose -f docker-compose.yml build - - docker push $SCCS_REGISTRY/sccs/scheduler/scheduler:latest + - docker push $SCCS_REGISTRY/sccs/planner/planner:latest deploy_docker_stage: stage: deploy variables: DOCKER_HOST: "tcp://130.58.218.21:2376" script: - - docker stack deploy --with-registry-auth -c ./docker-compose.yml scheduler + - docker stack deploy --with-registry-auth -c ./docker-compose.yml planner diff --git a/README.md b/README.md index 11bb9b5..c7c538d 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ ![repo_size] ![build_status] -

Looking to plan your classes? Visit the live site!

+

Looking to plan your classes? Visit the live site!

## 🏁 Getting Started @@ -31,9 +31,9 @@ ### Clone the Repo ```bash - git clone --recursive https://github.com/swat-sccs/scheduler-v2.git + git clone --recursive https://github.com/swat-sccs/planner.git git checkout dev - cd scheduler-v2 + cd planner ``` ### Configure your .env file @@ -41,15 +41,16 @@ Paste the following into a .env in the root of the project. ```bash -echo 'DATABASE_URL="postgresql://postgres:example@localhost:5432/scheduler_db"' > .env +echo 'DATABASE_URL="postgresql://postgres:example@localhost:5432/planner_db"' > .env ``` Pase the following into a .env in the /swatscraper dir + ```bash - echo 'HOST=localhost + echo 'HOST=localhost SQL_USER=postgres PASS=example - DBNAME=scheduler_db + DBNAME=planner_db OPMODE="DEV"' > ./swatscraper/.env ``` @@ -93,12 +94,12 @@ Head on over to http://localhost:5555. Use this to confirm your database is popu ## License -Licensed under the [MIT license](https://github.com/swat-sccs/scheduler-v2/blob/main/LICENSE). +Licensed under the [MIT license](https://github.com/swat-sccs/planner/blob/main/LICENSE). [repo_license_img]: https://img.shields.io/badge/license-Mit-red?style=for-the-badge&logo=none -[repo_license_url]: https://github.com/swat-sccs/scheduler-v2?tab=MIT-1-ov-file#readme -[repo_last_commit]: https://img.shields.io/github/last-commit/swat-sccs/scheduler-v2?style=for-the-badge&link=https%3A%2F%2Fgithub.com%2Fswat-sccs%2Fscheduler-v2&color=%2343AA8B -[build_status]: https://img.shields.io/github/check-runs/swat-sccs/scheduler-v2/main?style=for-the-badge&label=Build&color=%2343AA8B -[repo_size]: https://img.shields.io/github/repo-size/swat-sccs/scheduler-v2?style=for-the-badge +[repo_license_url]: https://github.com/swat-sccs/planner?tab=MIT-1-ov-file#readme +[repo_last_commit]: https://img.shields.io/github/last-commit/swat-sccs/planner?style=for-the-badge&link=https%3A%2F%2Fgithub.com%2Fswat-sccs%2Fplanner&color=%2343AA8B +[build_status]: https://img.shields.io/github/check-runs/swat-sccs/planner/main?style=for-the-badge&label=Build&color=%2343AA8B +[repo_size]: https://img.shields.io/github/repo-size/swat-sccs/planner?style=for-the-badge diff --git a/app/actions/getCourses.ts b/app/actions/getCourses.ts index 2bf561e..929d838 100644 --- a/app/actions/getCourses.ts +++ b/app/actions/getCourses.ts @@ -3,11 +3,114 @@ import { cookies } from "next/headers"; import prisma from "../../lib/prisma"; import { Prisma } from "@prisma/client"; +import { auth } from "@/lib/auth"; +import { getPlanCookie } from "./actions"; + +export async function getUniqueCodes() { + const codes = await prisma.sectionAttribute.findMany(); + const daCodes: any = []; + + for (let i = 0; i < codes.length; i++) { + if (!daCodes.includes(codes[i].code)) { + daCodes.push(codes[i].code); + } + } + + return daCodes; +} + +export async function getUniqueStartEndTimes() { + const meetingTimes = await prisma.meetingTime.findMany({ + where: { + beginTime: { not: "" }, + }, + orderBy: { + beginTime: "asc", + }, + }); + const startTimes: any = []; + const endTimes: any = []; + + for (let i = 0; i < meetingTimes.length; i++) { + if (!startTimes.includes(meetingTimes[i].beginTime)) { + startTimes.push(meetingTimes[i].beginTime); + } + if (!endTimes.includes(meetingTimes[i].endTime)) { + endTimes.push(meetingTimes[i].endTime); + } + } + + const times = { startTimes: startTimes, endTimes: endTimes }; + + return times; +} + +export async function getTerms() { + const courses = await prisma.course.findMany(); + const output: any = []; + + for (let i = 0; i < courses.length; i++) { + if (!output.includes(courses[i].year)) { + output.push(courses[i].year); + } + } + + return output; +} + export async function setPlanCookie(plan: string) { //@ts-ignore (await cookies()).set("plan", plan); } +export async function getPlanCourses1() { + const planCookie: any = await getPlanCookie(); + const session = await auth(); + + return await prisma.coursePlan.findMany({ + where: { + AND: { + User: { + uuid: session?.user.id, + }, + //id: parseInt(planCookie), + }, + }, + include: { + courses: true, + }, + }); +} + +export async function getPlanCourses(planID: any) { + //let DOTW: Array = dotw.split(","); + + return await prisma.course.findMany({ + relationLoadStrategy: "join", // or 'query' + where: { + CoursePlan: { + some: { + id: parseInt(planID), + }, + }, + }, + include: { + CoursePlan: true, + }, + }); +} + +export async function getInitialCoursePlans() { + //let DOTW: Array = dotw.split(","); + + return await prisma.coursePlan.findMany({ + relationLoadStrategy: "join", // or 'query' + include: { + courses: true, + }, + }); +} + export async function getInitialCourses( query: any, term: any, @@ -15,91 +118,15 @@ export async function getInitialCourses( stime: any ) { const startTime = stime.toString().split(",").filter(Number); - return await prisma.course.findMany({ relationLoadStrategy: "join", // or 'query' take: 20, - where: { ...(term ? { year: term, } : {}), - //year: term, - - ...(query - ? { - OR: [ - { - courseTitle: { - search: query.trim().split(" ").join(" | "), - mode: "insensitive", - }, - }, - { - sectionAttributes: { - some: { - code: { - search: query.trim().split(" ").join(" | "), - mode: "insensitive", - }, - }, - }, - }, - { - subject: { - search: query.trim().split(" ").join(" | "), - mode: "insensitive", - }, - }, - { - courseNumber: { - search: query.trim().split(" ").join(" | "), - mode: "insensitive", - }, - }, - { - instructor: { - displayName: { - search: query.trim().split(" ").join(" | "), - mode: "insensitive", - }, - }, - }, - ], - } - : {}), - - ...(startTime.length > 0 - ? { - facultyMeet: { - meetingTimes: { - beginTime: { - in: startTime, - }, - }, - }, - } - : {}), - - ...(dotw.length > 0 - ? { - facultyMeet: { - meetingTimes: { - is: { - monday: dotw.includes("monday") ? true : Prisma.skip, - tuesday: dotw.includes("tuesday") ? true : Prisma.skip, - wednesday: dotw.includes("wednesday") ? true : Prisma.skip, - thursday: dotw.includes("thursday") ? true : Prisma.skip, - friday: dotw.includes("friday") ? true : Prisma.skip, - saturday: dotw.includes("saturday") ? true : Prisma.skip, - sunday: dotw.includes("sunday") ? true : Prisma.skip, - }, - }, - }, - } - : {}), }, include: { @@ -116,19 +143,16 @@ export async function getInitialCourses( export async function getCourses( take: any, - cursor: any, query: any, term: any, dotw: any, stime: any ) { const startTime = stime.toString().split(",").filter(Number); + return await prisma.course.findMany({ relationLoadStrategy: "join", // or 'query' take: take, - cursor: { - id: 1, - }, include: { sectionAttributes: true, @@ -140,15 +164,19 @@ export async function getCourses( instructor: true, }, - orderBy: [ - { - _relevance: { - fields: ["courseTitle", "subject", "courseNumber"], - search: query.trim().split(" ").join(" & "), - sort: "desc", - }, - }, - ], + ...(query + ? { + orderBy: [ + { + _relevance: { + fields: ["courseTitle", "subject", "courseNumber"], + search: query.trim().split(" ").join(" & "), + sort: "desc", + }, + }, + ], + } + : ""), where: { ...(term ? { diff --git a/app/page.tsx b/app/page.tsx index f120379..0bccd38 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -6,61 +6,15 @@ import { cookies } from "next/headers"; import Search from "../components/Search"; import { FullCourseList } from "../components/FullCourseList"; import CreatePlan from "../components/CreatePlan"; -import prisma from "../lib/prisma"; -import { getInitialCourses } from "../app/actions/getCourses"; +import { + getInitialCourses, + getPlanCourses1, + getTerms, + getUniqueStartEndTimes, + getUniqueCodes, +} from "../app/actions/getCourses"; import { redirect } from "next/navigation"; - -async function getCourses() { - const courses = await prisma.course.findMany(); - const output: any = []; - - for (let i = 0; i < courses.length; i++) { - if (!output.includes(courses[i].year)) { - output.push(courses[i].year); - } - } - - return output; -} - -async function getUniqueStartEndTimes() { - const meetingTimes = await prisma.meetingTime.findMany({ - where: { - beginTime: { not: "" }, - }, - orderBy: { - beginTime: "asc", - }, - }); - const startTimes: any = []; - const endTimes: any = []; - - for (let i = 0; i < meetingTimes.length; i++) { - if (!startTimes.includes(meetingTimes[i].beginTime)) { - startTimes.push(meetingTimes[i].beginTime); - } - if (!endTimes.includes(meetingTimes[i].endTime)) { - endTimes.push(meetingTimes[i].endTime); - } - } - - const times = { startTimes: startTimes, endTimes: endTimes }; - - return times; -} - -async function getUniquCodes() { - const codes = await prisma.sectionAttribute.findMany(); - const daCodes: any = []; - - for (let i = 0; i < codes.length; i++) { - if (!daCodes.includes(codes[i].code)) { - daCodes.push(codes[i].code); - } - } - - return daCodes; -} +import { CoursePlan } from "@prisma/client"; export default async function Page(props: { searchParams?: Promise<{ @@ -72,10 +26,9 @@ export default async function Page(props: { }>; }) { const cookieStore = await cookies(); + const planID = await cookieStore.get("plan"); const pagePref = cookieStore.get("pagePref"); if (pagePref && pagePref.value != "plan") { - console.log("wtf"); - console.log(pagePref.value); redirect("/" + pagePref.value); } @@ -86,6 +39,7 @@ export default async function Page(props: { const stime = searchParams?.stime || []; const homePageProps: any = {}; const initalCourses = await getInitialCourses(query, term, dotw, stime); + const planCourses: CoursePlan[] = await getPlanCourses1(); homePageProps["fullCourseList"] = ( } > - + ); return ; // return with no events } async function Home(props: any) { - const terms = await getCourses(); + const terms = await getTerms(); const uniqueTimes = await getUniqueStartEndTimes(); - const codes = await getUniquCodes(); + const codes = await getUniqueCodes(); return ( <> @@ -136,7 +90,7 @@ async function Home(props: any) {
- + {props.createPlan}
diff --git a/components/FullCourseList.tsx b/components/FullCourseList.tsx index 8a8ac76..296df0e 100644 --- a/components/FullCourseList.tsx +++ b/components/FullCourseList.tsx @@ -38,7 +38,7 @@ export function FullCourseList({ setCursor((cursor) => cursor + NUMBER_OF_USERS_TO_FETCH); setTake((take) => take + NUMBER_OF_USERS_TO_FETCH); - const apiCourses = await getCourses(take, cursor, query, term, dotw, stime); + const apiCourses = await getCourses(take, query, term, dotw, stime); if ( inView && (apiCourses.length == 0 || apiCourses.length == courses.length) diff --git a/components/OLD.FullCourseList.tsx b/components/OLD.FullCourseList.tsx deleted file mode 100644 index ab2e7bc..0000000 --- a/components/OLD.FullCourseList.tsx +++ /dev/null @@ -1,149 +0,0 @@ -import { Course, Prisma } from "@prisma/client"; - -import prisma from "../lib/prisma"; - -import CourseCard from "./CourseCard"; -import React from "react"; - -async function getCourses( - query: string, - term: string, - dotw: Array, - stime: Array -) { - //let DOTW: Array = dotw.split(","); - - //query = query.trim().replace(/^[a-zA-Z0-9:]+$/g, ""); - - const startTime = stime.toString().split(",").filter(Number); - - return await prisma.course.findMany({ - relationLoadStrategy: "join", // or 'query' - include: { - sectionAttributes: true, - facultyMeet: { - include: { - meetingTimes: true, - }, - }, - instructor: true, - }, - - orderBy: [ - { - _relevance: { - fields: ["courseTitle", "subject", "courseNumber"], - search: query.trim().split(" ").join(" & "), - sort: "desc", - }, - }, - ], - where: { - ...(term - ? { - year: term, - } - : {}), - //year: term, - - ...(query - ? { - OR: [ - { - courseTitle: { - search: query.trim().split(" ").join(" | "), - mode: "insensitive", - }, - }, - { - sectionAttributes: { - some: { - code: { - search: query.trim().split(" ").join(" | "), - mode: "insensitive", - }, - }, - }, - }, - { - subject: { - search: query.trim().split(" ").join(" | "), - mode: "insensitive", - }, - }, - { - courseNumber: { - search: query.trim().split(" ").join(" | "), - mode: "insensitive", - }, - }, - { - instructor: { - displayName: { - search: query.trim().split(" ").join(" | "), - mode: "insensitive", - }, - }, - }, - ], - } - : {}), - - ...(startTime.length > 0 - ? { - facultyMeet: { - meetingTimes: { - beginTime: { - in: startTime, - }, - }, - }, - } - : {}), - - ...(dotw.length > 0 - ? { - facultyMeet: { - meetingTimes: { - is: { - monday: dotw.includes("monday") ? true : Prisma.skip, - tuesday: dotw.includes("tuesday") ? true : Prisma.skip, - wednesday: dotw.includes("wednesday") ? true : Prisma.skip, - thursday: dotw.includes("thursday") ? true : Prisma.skip, - friday: dotw.includes("friday") ? true : Prisma.skip, - saturday: dotw.includes("saturday") ? true : Prisma.skip, - sunday: dotw.includes("sunday") ? true : Prisma.skip, - }, - }, - }, - } - : {}), - }, - }); -} - -export async function FullCourseList({ - query, - term, - dotw, - stime, -}: { - query: string; - term: string; - dotw: Array; - stime: Array; -}) { - const courseList: Course[] = await getCourses(query, term, dotw, stime); - - return ( - <> -
- {courseList?.map((course: any) => ( -
- -
- ))} -
- - ); -} diff --git a/components/PlanContext.tsx b/components/PlanContext.tsx new file mode 100644 index 0000000..2119847 --- /dev/null +++ b/components/PlanContext.tsx @@ -0,0 +1,24 @@ +"use client"; +import { createContext, useContext, useState } from "react"; +import { CoursePlan } from "@prisma/client"; +import { getInitialCoursePlans } from "../app/actions/getCourses"; + +const PlanContext = createContext([]); + +export const PlanContextProvider = ({ + children, +}: { + children: React.ReactNode; +}) => { + const [coursePlans, setCoursePlans] = useState([]); + + return ( + + {children} + + ); +}; + +export const usePlanContext = () => { + return useContext(PlanContext); +}; diff --git a/components/Search.tsx b/components/Search.tsx index 33e80c9..072bb8b 100644 --- a/components/Search.tsx +++ b/components/Search.tsx @@ -47,7 +47,7 @@ export default function Search(props: any) { params.delete("query"); } replace(`${pathname}?${params.toString()}`); - }); + }, 100); const handleSelectionChange = (e: any) => { setSelectedTerm([e.target.value]); @@ -86,6 +86,7 @@ export default function Search(props: any) { searchParams.get("dotw")?.toString(), searchParams.get("stime")?.toString(), ]); + useEffect(() => { // Update the document title using the browser API params.set("term", "S2025"); diff --git a/components/primitives.ts b/components/primitives.ts index 6607a15..8d503db 100644 --- a/components/primitives.ts +++ b/components/primitives.ts @@ -81,8 +81,8 @@ export function generateColorFromName(name: string) { hash += name.charCodeAt(i) * i; } - console.log("generated:"); - console.log(courseColors[hash % courseColors.length]); + //console.log("generated:"); + //console.log(courseColors[hash % courseColors.length]); return courseColors[hash % courseColors.length]; } diff --git a/docker-compose.debug.yml b/docker-compose.debug.yml index a389da7..1a94fa4 100644 --- a/docker-compose.debug.yml +++ b/docker-compose.debug.yml @@ -1,5 +1,6 @@ services: - schedulerv2: + planner-dev: + container_name: planner-dev build: context: . dockerfile: ./Dockerfile.dev @@ -8,8 +9,7 @@ services: environment: NODE_ENV: development DOMAIN: http://127.0.0.1:3000/ - DATABASE_URL: "postgresql://postgres:example@postgres:5432/scheduler_db" - POSTGRES_DB: scheduler_db + POSTGRES_DB: planner_db env_file: - .env ports: @@ -19,13 +19,14 @@ services: - internal command: sh -c "npm install --silent && npx prisma migrate dev --name init && npx prisma generate && npm run dev " - postgres: + planner-db-dev: + container_name: planner-db-dev image: postgres:16.4-bullseye ports: - 5432:5432 environment: POSTGRES_PASSWORD: example - POSTGRES_DB: scheduler_db + POSTGRES_DB: planner_db networks: - internal volumes: diff --git a/docker-compose.yml b/docker-compose.yml index 341ea2c..887f8ee 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,6 +1,6 @@ services: - scheduler: - image: registry.sccs.swarthmore.edu/sccs/scheduler/scheduler:latest + planner: + image: registry.sccs.swarthmore.edu/sccs/planner/planner:latest build: context: . dockerfile: ./Dockerfile @@ -9,28 +9,28 @@ services: - .env environment: NODE_ENV: production - DOMAIN: https://schedulerv2.sccs.swarthmore.edu + DOMAIN: https://plan.sccs.swarthmore.edu depends_on: - - scheduler-db + - planner-db deploy: labels: - - 'traefik.enable=true' - - 'traefik.docker.network=traefik' - - 'traefik.http.routers.scheduler.entrypoints=https' - - 'traefik.http.routers.scheduler.rule=Host(`schedulerv2.sccs.swarthmore.edu`)' - - 'traefik.http.routers.scheduler.tls=true' - - 'traefik.http.routers.scheduler.tls.certresolver=letsEncrypt' - - 'traefik.http.services.scheduler.loadbalancer.server.port=3000' + - "traefik.enable=true" + - "traefik.docker.network=traefik" + - "traefik.http.routers.planner.entrypoints=https" + - "traefik.http.routers.planner.rule=Host(`plan.sccs.swarthmore.edu`)" + - "traefik.http.routers.planner.tls=true" + - "traefik.http.routers.planner.tls.certresolver=letsEncrypt" + - "traefik.http.services.planner.loadbalancer.server.port=3000" command: sh -c "sleep 5 && npx prisma migrate deploy && npm start " networks: - traefik - internal - scheduler-db: - hostname: scheduler-db + planner-db: + hostname: planner-db image: postgres:16.4-bullseye volumes: - - scheduler-dbdata:/var/lib/postgresql/data + - planner-dbdata:/var/lib/postgresql/data env_file: - .env ports: @@ -38,8 +38,8 @@ services: networks: - internal - scheduler-cron: - image: registry.sccs.swarthmore.edu/sccs/scheduler/scheduler-cron:latest + planner-cron: + image: registry.sccs.swarthmore.edu/sccs/planner/planner-cron:latest build: context: . dockerfile: ./Dockerfile.cron @@ -47,7 +47,7 @@ services: env_file: - .env depends_on: - - scheduler-db + - planner-db networks: - internal @@ -60,9 +60,9 @@ networks: external: true volumes: - scheduler-dbdata: - name: scheduler-dbdata + planner-dbdata: + name: planner-dbdata driver_opts: type: nfs o: "nfsvers=4,addr=130.58.218.26,rw,nolock,soft" - device: ":/volumes/scheduler-dbdata" + device: ":/volumes/planner-dbdata" diff --git a/package-lock.json b/package-lock.json index 9b6347f..8deb37a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { - "name": "scheduler", + "name": "planner", "version": "2.0.0-beta", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "scheduler", + "name": "planner", "version": "2.0.0-beta", "dependencies": { "@emotion/react": "^11.13.3", diff --git a/package.json b/package.json index 46fab0b..1e76200 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "scheduler", + "name": "planner", "version": "2.0.0-beta", "private": true, "scripts": {