From 7561ad6cb5f793a8f841861890571d0328b0bb80 Mon Sep 17 00:00:00 2001 From: thePeras Date: Wed, 9 Oct 2024 23:45:18 +0100 Subject: [PATCH 01/14] ci: sentry release and source map uploads --- .github/workflows/release_version.yaml | 50 +++++++++++++++++++ .github/workflows/sentry.yaml | 66 ++++++++++++++++++++++++++ 2 files changed, 116 insertions(+) create mode 100644 .github/workflows/release_version.yaml create mode 100644 .github/workflows/sentry.yaml diff --git a/.github/workflows/release_version.yaml b/.github/workflows/release_version.yaml new file mode 100644 index 00000000..28713564 --- /dev/null +++ b/.github/workflows/release_version.yaml @@ -0,0 +1,50 @@ +name: Check Package Version + +on: + pull_request: + branches: + - main + +jobs: + check_version: + runs-on: ubuntu-latest + + steps: + - name: Checkout PR branch code + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Set up Node.js + uses: actions/setup-node@v3 + with: + node-version: '20' + + - name: Get PR package version + id: pr_version + run: | + PR_VERSION=$(jq -r .version < package.json) + echo "::set-output name=pr_version::$PR_VERSION" + + - name: Fetch and checkout the main branch + run: | + git fetch origin main + git checkout origin/main + + - name: Compare PR versions + run: | + PR_VERSION=${{ steps.pr_version.outputs.pr_version }} + MAIN_VERSION=$(jq -r .version < package.json) + echo "Main branch version: $MAIN_VERSION" + echo "PR version: $PR_VERSION" + + version_greater() { + printf '%s\n%s' "$1" "$2" | sort -V | head -n1 | grep -q "$2" + } + + if version_greater "$PR_VERSION" "$MAIN_VERSION"; then + echo "Version is correct!" + else + echo "Error: PR version ($PR_VERSION) is not greater than main version ($MAIN_VERSION)." + exit 1 + fi diff --git a/.github/workflows/sentry.yaml b/.github/workflows/sentry.yaml new file mode 100644 index 00000000..b26e9765 --- /dev/null +++ b/.github/workflows/sentry.yaml @@ -0,0 +1,66 @@ +name: Sentry Release + +on: + push: + branches: + - main + - develop + +jobs: + release: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Set up Node.js + uses: actions/setup-node@v3 + with: + node-version: '20' + + - name: Install dependencies + run: yarn install + + - name: Build project + run: yarn build + + - name: Determine release version + id: get_version + run: | + VERSION=$(jq -r .version < package.json) + + # If the branch is develop, use the commit hash as the version + if [ "${{ github.ref }}" == "refs/heads/develop" ]; then + VERSION=$(git rev-parse --short HEAD) + fi + + echo "Version to be released: $VERSION" + echo "::set-output name=release_version::$VERSION" + + - name: Install Sentry CLI + run: npm install -g @sentry/cli + + - name: Create Sentry release + env: + SENTRY_ORG: ${{ secrets.SENTRY_ORG }} + SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }} + SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} + run: | + sentry-cli releases new ${{ steps.get_version.outputs.release_version }} + sentry-cli releases set-commits --auto ${{ steps.get_version.outputs.release_version }} + + - name: Upload source maps to Sentry + env: + SENTRY_ORG: ${{ secrets.SENTRY_ORG }} + SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }} + SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} + run: | + sentry-cli releases files ${{ steps.get_version.outputs.release_version }} upload-sourcemaps ./build + + - name: Finalize Sentry release + env: + SENTRY_ORG: ${{ secrets.SENTRY_ORG }} + SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }} + SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} + run: sentry-cli releases finalize ${{ steps.get_version.outputs.release_version }} From 39115abe0d5a4a844ed0ad3de2050824e54d842f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Palma?= Date: Thu, 17 Oct 2024 19:18:09 +0100 Subject: [PATCH 02/14] chore: sentry tracing report disabled by default in dev mode --- .env.example | 5 ++++- src/App.tsx | 12 ++++++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/.env.example b/.env.example index 02cde089..a2a581ef 100644 --- a/.env.example +++ b/.env.example @@ -7,5 +7,8 @@ VITE_APP_SEMESTER= VITE_APP_SITE_TITLE= VITE_APP_BACKEND_URL= +VITE_APP_SENTRY_DSN=https://01f0882e6aa029a125426e4ad32e6c18@o553498.ingest.us.sentry.io/4507775325437952 +VITE_APP_SENTRY_TRACING=0 + # To upload source maps to Sentry (Optional) -SENTRY_AUTH_TOKEN= +APP_SENTRY_AUTH_TOKEN= diff --git a/src/App.tsx b/src/App.tsx index 8c511a0b..afd77e2b 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -36,17 +36,17 @@ const App = () => { // Enable Error Tracking, Performance Monitoring and Session Replay Sentry.init({ environment: Number(import.meta.env.VITE_APP_PROD) ? "production" : "development", - dsn: "https://01f0882e6aa029a125426e4ad32e6c18@o553498.ingest.us.sentry.io/4507775325437952", + dsn: import.meta.env.VITE_APP_SENTRY_DSN, integrations: [ - Sentry.browserTracingIntegration(), - Sentry.replayIntegration(), - Sentry.reactRouterV6BrowserTracingIntegration({ + import.meta.env.VITE_APP_SENTRY_TRACING ? Sentry.browserTracingIntegration() : null, + import.meta.env.VITE_APP_SENTRY_TRACING ? Sentry.replayIntegration() : null, + import.meta.env.VITE_APP_SENTRY_TRACING ? Sentry.reactRouterV6BrowserTracingIntegration({ useEffect: React.useEffect, useLocation, useNavigationType, createRoutesFromChildren, matchRoutes, - }), + }) : null, ], // Performance monitoring @@ -71,7 +71,7 @@ const App = () => {
- +
} From b7328dbe36040d12ca0e0410055893c7d6b58fba Mon Sep 17 00:00:00 2001 From: thePeras Date: Fri, 1 Nov 2024 11:06:49 +0000 Subject: [PATCH 03/14] Update sentry workflow to use the marketplace action --- .github/workflows/sentry.yaml | 39 +++++++++++------------------------ 1 file changed, 12 insertions(+), 27 deletions(-) diff --git a/.github/workflows/sentry.yaml b/.github/workflows/sentry.yaml index b26e9765..f5b40e76 100644 --- a/.github/workflows/sentry.yaml +++ b/.github/workflows/sentry.yaml @@ -25,42 +25,27 @@ jobs: - name: Build project run: yarn build - - name: Determine release version + - name: Determine release version (default to commit hash) id: get_version run: | - VERSION=$(jq -r .version < package.json) + VERSION=$(git rev-parse --short HEAD) - # If the branch is develop, use the commit hash as the version - if [ "${{ github.ref }}" == "refs/heads/develop" ]; then - VERSION=$(git rev-parse --short HEAD) + # Override version if on main branch to use package.json version + if [ "${{ github.ref }}" == "refs/heads/main" ]; then + VERSION=$(jq -r .version < package.json) fi echo "Version to be released: $VERSION" echo "::set-output name=release_version::$VERSION" - - name: Install Sentry CLI - run: npm install -g @sentry/cli - - - name: Create Sentry release - env: - SENTRY_ORG: ${{ secrets.SENTRY_ORG }} - SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }} - SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} - run: | - sentry-cli releases new ${{ steps.get_version.outputs.release_version }} - sentry-cli releases set-commits --auto ${{ steps.get_version.outputs.release_version }} - - - name: Upload source maps to Sentry + - name: Create and Finalize Sentry Release + uses: getsentry/action-release@v1 + with: + environment: ${{ github.ref == 'refs/heads/main' && 'production' || 'staging' }} + version: ${{ steps.get_version.outputs.release_version }} + sourcemaps: ./build + finalize: true env: - SENTRY_ORG: ${{ secrets.SENTRY_ORG }} - SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }} SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} - run: | - sentry-cli releases files ${{ steps.get_version.outputs.release_version }} upload-sourcemaps ./build - - - name: Finalize Sentry release - env: SENTRY_ORG: ${{ secrets.SENTRY_ORG }} SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }} - SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} - run: sentry-cli releases finalize ${{ steps.get_version.outputs.release_version }} From 019a7a80ccd7ccd917598048ce16c8c35b850294 Mon Sep 17 00:00:00 2001 From: thePeras Date: Sat, 2 Nov 2024 15:25:10 +0000 Subject: [PATCH 04/14] Create sentry environment --- .github/workflows/sentry.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/sentry.yaml b/.github/workflows/sentry.yaml index f5b40e76..e4d4f409 100644 --- a/.github/workflows/sentry.yaml +++ b/.github/workflows/sentry.yaml @@ -9,6 +9,8 @@ on: jobs: release: runs-on: ubuntu-latest + environment: + name: sentry steps: - name: Checkout code From 5c266225adeca9570f1c5841626625debc14dcb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Palma?= Date: Fri, 18 Oct 2024 00:16:45 +0100 Subject: [PATCH 05/14] fix: class item conflict indicator correct severity --- .../sidebar/CoursesController/ClassItem.tsx | 41 +++++++++---------- .../ClassSelectorDropdownController.tsx | 11 +---- src/utils/index.ts | 17 +++++++- 3 files changed, 36 insertions(+), 33 deletions(-) diff --git a/src/components/planner/sidebar/CoursesController/ClassItem.tsx b/src/components/planner/sidebar/CoursesController/ClassItem.tsx index 13769b51..b8bc0332 100644 --- a/src/components/planner/sidebar/CoursesController/ClassItem.tsx +++ b/src/components/planner/sidebar/CoursesController/ClassItem.tsx @@ -1,8 +1,8 @@ -import { useContext, useMemo } from 'react' +import { useContext } from 'react' import { ClassInfo } from '../../../../@types/index' import { DropdownMenuCheckboxItem } from '../../../ui/dropdown-menu' import { ExclamationTriangleIcon } from '@heroicons/react/20/solid' -import { conflictsSeverity, schedulesConflict } from '../../../../utils' +import { classesConflictSeverity } from '../../../../utils' import MultipleOptionsContext from '../../../../contexts/MultipleOptionsContext' import CourseContext from '../../../../contexts/CourseContext' @@ -10,7 +10,6 @@ import CourseContext from '../../../../contexts/CourseContext' type Props = { course_id: number, classInfo: ClassInfo - conflict?: boolean onSelect?: () => void onMouseEnter?: () => void onMouseLeave?: () => void @@ -29,26 +28,26 @@ const ClassItem = ({ course_id, classInfo, onSelect, onMouseEnter, onMouseLeave onSelect(); } - const conflict: number = useMemo(() => { - const classes: ClassInfo[] = [] + const conflictSeverity = () => { + const chosenCourses = multipleOptions[selectedOption].course_options.filter( + (option) => option.course_id !== course_id + ); - for (const course_option of multipleOptions[selectedOption].course_options) { - if (course_option.picked_class_id && course_option.course_id !== course_id) { - const pickedCourse = pickedCourses.find(co => co.id === course_option.course_id); - // retrieve class with the picked class id of the course option - const pickedClass = pickedCourse.classes.find(c => c.id === course_option.picked_class_id); + const otherClasses = []; + chosenCourses.forEach((option) => { + const courseInfo = pickedCourses.find((course) => course.id === option.course_id); + const pickedClass = courseInfo.classes.find((classInfo) => classInfo.id === option.picked_class_id); - classes.push(pickedClass); - } + if (pickedClass) otherClasses.push(pickedClass); + }); + + let maxSeverity = 0; + for (const otherClass of otherClasses) { + maxSeverity = Math.max(maxSeverity, classesConflictSeverity(classInfo, otherClass)); } - for (const pickedClass of classes) - for (const slot1 of pickedClass.slots) - for (const slot2 of classInfo.slots) - if (schedulesConflict(slot1, slot2)) { - return conflictsSeverity(slot1, slot2); - } - }, []); + return maxSeverity; + } return ( (
{slot.lesson_type} - {/* {convertWeekday(slot.day)} */} - {/* {getLessonBoxTime(slot)} */} {slot.location} {slot.professors.map((professor) => professor.acronym).join(', ')} @@ -72,7 +69,7 @@ const ClassItem = ({ course_id, classInfo, onSelect, onMouseEnter, onMouseLeave ))}
-
) } diff --git a/src/components/planner/sidebar/CoursesController/ClassSelectorDropdownController.tsx b/src/components/planner/sidebar/CoursesController/ClassSelectorDropdownController.tsx index a5d42203..bf064d62 100644 --- a/src/components/planner/sidebar/CoursesController/ClassSelectorDropdownController.tsx +++ b/src/components/planner/sidebar/CoursesController/ClassSelectorDropdownController.tsx @@ -4,7 +4,7 @@ import { ClassInfo, CourseInfo, CourseOption, ProfessorInfo } from "../../../../ import StorageAPI from "../../../../api/storage"; import CourseContext from "../../../../contexts/CourseContext"; import MultipleOptionsContext from "../../../../contexts/MultipleOptionsContext"; -import { getAllPickedSlots, schedulesConflict, teacherIdsFromCourseInfo, uniqueTeachersFromCourseInfo } from "../../../../utils"; +import { teacherIdsFromCourseInfo, uniqueTeachersFromCourseInfo } from "../../../../utils"; import { Desert } from "../../../svgs"; import { DropdownMenuGroup, DropdownMenuItem, DropdownMenuPortal, DropdownMenuSeparator, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger } from "../../../ui/dropdown-menu"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "../../../ui/tabs"; @@ -157,13 +157,6 @@ const ClassSelectorDropdownController = ({ setMultipleOptions(newMultipleOptions) } - // Checks if any of the selected classes have time conflicts with the classInfo - // This is used to display a warning icon in each class of the dropdown in case of conflicts - const timesCollideWithSelected = (classInfo: ClassInfo) => { - const pickedSlots = getAllPickedSlots(pickedCourses, multipleOptions[selectedOption]) - return pickedSlots.some((slot) => classInfo.slots.some((currentSlot) => schedulesConflict(slot, currentSlot))) - } - return <>
{course.classes === null ? ( @@ -226,7 +219,6 @@ const ClassSelectorDropdownController = ({ key={`schedule-${classInfo.name}`} course_id={course.id} classInfo={classInfo} - conflict={timesCollideWithSelected(classInfo)} onSelect={() => { setSelectedClassId(classInfo.id) setPreview(null) @@ -260,7 +252,6 @@ const ClassSelectorDropdownController = ({ key={`schedule-${classInfo.name}`} course_id={course.id} classInfo={classInfo} - conflict={timesCollideWithSelected(classInfo)} onSelect={() => { setSelectedClassId(classInfo.id) setPreview(null) diff --git a/src/utils/index.ts b/src/utils/index.ts index 9a26ab6f..af71ab82 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,6 +1,6 @@ import config from '../config/prod.json' import dev_config from '../config/local.json' -import { CourseInfo, CourseOption, SlotInfo, MultipleOptions, Option, PickedCourses, ProfessorInfo } from '../@types' +import { CourseInfo, CourseOption, SlotInfo, MultipleOptions, Option, PickedCourses, ProfessorInfo, ClassInfo } from '../@types' import { type ClassValue, clsx } from 'clsx' import { twMerge } from 'tailwind-merge' import Plausible from 'plausible-tracker' @@ -77,6 +77,20 @@ const conflictsSeverity = (first: SlotInfo, second: SlotInfo): number => { return (isMandatory(first) && isMandatory(second)) ? 2 : 1; } +const classesConflictSeverity = (first: ClassInfo, second: ClassInfo): number => { + let maxSeverity = 0; + + for (const slot of first.slots) { + for (const otherSlot of second.slots) { + if (schedulesConflict(slot, otherSlot)) { + maxSeverity = Math.max(maxSeverity, conflictsSeverity(slot, otherSlot)); + } + } + } + + return maxSeverity; +} + const schedulesConflict = (first: SlotInfo, second: SlotInfo) => { if (first.day !== second.day) return false @@ -395,5 +409,6 @@ export { uniqueTeachersFromCourseInfo, teacherIdsFromCourseInfo, scrollToTop, + classesConflictSeverity, plausible } From d7979462f5e18f0e840c2d944713bdabedbca2c4 Mon Sep 17 00:00:00 2001 From: Rodrigo Nunes Date: Wed, 6 Nov 2024 19:01:50 +0000 Subject: [PATCH 06/14] =?UTF-8?q?enhancement:=20Remover=20sele=C3=A7=C3=A3?= =?UTF-8?q?o=20should=20appear=20only=20when=20there=20is=20a=20major=20se?= =?UTF-8?q?lected?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CoursesController/ClassSelectorDropdownController.tsx | 2 ++ .../sessionController/course-picker/MajorSearchCombobox.tsx | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/components/planner/sidebar/CoursesController/ClassSelectorDropdownController.tsx b/src/components/planner/sidebar/CoursesController/ClassSelectorDropdownController.tsx index a5d42203..2268044b 100644 --- a/src/components/planner/sidebar/CoursesController/ClassSelectorDropdownController.tsx +++ b/src/components/planner/sidebar/CoursesController/ClassSelectorDropdownController.tsx @@ -217,9 +217,11 @@ const ClassSelectorDropdownController = ({ {!course.classes || course.classes.length === 0 ? : <> + {selectedClassId && ( deleteOption()}> Remover Seleção + )} {course.classes && getOptions().map((classInfo) => ( { // handle that event and actually be scrollable with the mouse wheel onWheel={(e) => e.stopPropagation()} > + {selectedMajor && ( setSelectedMajor(null)}> Remover Seleção + )} {majors && majors.map((major) => ( Date: Sat, 9 Nov 2024 14:52:50 +0000 Subject: [PATCH 07/14] chore(deps): bump rollup from 4.20.0 to 4.25.0 Bumps [rollup](https://github.com/rollup/rollup) from 4.20.0 to 4.25.0. - [Release notes](https://github.com/rollup/rollup/releases) - [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md) - [Commits](https://github.com/rollup/rollup/compare/v4.20.0...v4.25.0) --- updated-dependencies: - dependency-name: rollup dependency-type: indirect ... Signed-off-by: dependabot[bot] --- package-lock.json | 252 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 223 insertions(+), 29 deletions(-) diff --git a/package-lock.json b/package-lock.json index fbe55142..a39122fd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1661,10 +1661,166 @@ "node": ">= 8.0.0" } }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.25.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.25.0.tgz", + "integrity": "sha512-CC/ZqFZwlAIbU1wUPisHyV/XRc5RydFrNLtgl3dGYskdwPZdt4HERtKm50a/+DtTlKeCq9IXFEWR+P6blwjqBA==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.25.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.25.0.tgz", + "integrity": "sha512-/Y76tmLGUJqVBXXCfVS8Q8FJqYGhgH4wl4qTA24E9v/IJM0XvJCGQVSW1QZ4J+VURO9h8YCa28sTFacZXwK7Rg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.25.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.25.0.tgz", + "integrity": "sha512-YVT6L3UrKTlC0FpCZd0MGA7NVdp7YNaEqkENbWQ7AOVOqd/7VzyHpgIpc1mIaxRAo1ZsJRH45fq8j4N63I/vvg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.25.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.25.0.tgz", + "integrity": "sha512-ZRL+gexs3+ZmmWmGKEU43Bdn67kWnMeWXLFhcVv5Un8FQcx38yulHBA7XR2+KQdYIOtD0yZDWBCudmfj6lQJoA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.25.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.25.0.tgz", + "integrity": "sha512-xpEIXhiP27EAylEpreCozozsxWQ2TJbOLSivGfXhU4G1TBVEYtUPi2pOZBnvGXHyOdLAUUhPnJzH3ah5cqF01g==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.25.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.25.0.tgz", + "integrity": "sha512-sC5FsmZGlJv5dOcURrsnIK7ngc3Kirnx3as2XU9uER+zjfyqIjdcMVgzy4cOawhsssqzoAX19qmxgJ8a14Qrqw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.25.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.25.0.tgz", + "integrity": "sha512-uD/dbLSs1BEPzg564TpRAQ/YvTnCds2XxyOndAO8nJhaQcqQGFgv/DAVko/ZHap3boCvxnzYMa3mTkV/B/3SWA==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.25.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.25.0.tgz", + "integrity": "sha512-ZVt/XkrDlQWegDWrwyC3l0OfAF7yeJUF4fq5RMS07YM72BlSfn2fQQ6lPyBNjt+YbczMguPiJoCfaQC2dnflpQ==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.25.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.25.0.tgz", + "integrity": "sha512-qboZ+T0gHAW2kkSDPHxu7quaFaaBlynODXpBVnPxUgvWYaE84xgCKAPEYE+fSMd3Zv5PyFZR+L0tCdYCMAtG0A==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.25.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.25.0.tgz", + "integrity": "sha512-ndWTSEmAaKr88dBuogGH2NZaxe7u2rDoArsejNslugHZ+r44NfWiwjzizVS1nUOHo+n1Z6qV3X60rqE/HlISgw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.25.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.25.0.tgz", + "integrity": "sha512-BVSQvVa2v5hKwJSy6X7W1fjDex6yZnNKy3Kx1JGimccHft6HV0THTwNtC2zawtNXKUu+S5CjXslilYdKBAadzA==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.25.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.25.0.tgz", + "integrity": "sha512-G4hTREQrIdeV0PE2JruzI+vXdRnaK1pg64hemHq2v5fhv8C7WjVaeXc9P5i4Q5UC06d/L+zA0mszYIKl+wY8oA==", + "cpu": [ + "riscv64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.25.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.25.0.tgz", + "integrity": "sha512-9T/w0kQ+upxdkFL9zPVB6zy9vWW1deA3g8IauJxojN4bnz5FwSsUAD034KpXIVX5j5p/rn6XqumBMxfRkcHapQ==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ] + }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.20.0.tgz", - "integrity": "sha512-y+eoL2I3iphUg9tN9GB6ku1FA8kOfmF4oUEWhztDJ4KXJy1agk/9+pejOuZkNFhRwHAOxMsBPLbXPd6mJiCwew==", + "version": "4.25.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.25.0.tgz", + "integrity": "sha512-ThcnU0EcMDn+J4B9LD++OgBYxZusuA7iemIIiz5yzEcFg04VZFzdFjuwPdlURmYPZw+fgVrFzj4CA64jSTG4Ig==", "cpu": [ "x64" ], @@ -1674,9 +1830,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.20.0.tgz", - "integrity": "sha512-hM3nhW40kBNYUkZb/r9k2FKK+/MnKglX7UYd4ZUy5DJs8/sMsIbqWK2piZtVGE3kcXVNj3B2IrUYROJMMCikNg==", + "version": "4.25.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.25.0.tgz", + "integrity": "sha512-zx71aY2oQxGxAT1JShfhNG79PnjYhMC6voAjzpu/xmMjDnKNf6Nl/xv7YaB/9SIa9jDYf8RBPWEnjcdlhlv1rQ==", "cpu": [ "x64" ], @@ -1685,6 +1841,42 @@ "linux" ] }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.25.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.25.0.tgz", + "integrity": "sha512-JT8tcjNocMs4CylWY/CxVLnv8e1lE7ff1fi6kbGocWwxDq9pj30IJ28Peb+Y8yiPNSF28oad42ApJB8oUkwGww==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.25.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.25.0.tgz", + "integrity": "sha512-dRLjLsO3dNOfSN6tjyVlG+Msm4IiZnGkuZ7G5NmpzwF9oOc582FZG05+UdfTbz5Jd4buK/wMb6UeHFhG18+OEg==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.25.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.25.0.tgz", + "integrity": "sha512-/RqrIFtLB926frMhZD0a5oDa4eFIbyNEwLLloMTEjmqfwZWXywwVVOVmwTsuyhC9HKkVEZcOOi+KV4U9wmOdlg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@sentry-internal/browser-utils": { "version": "8.33.1", "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-8.33.1.tgz", @@ -2145,9 +2337,9 @@ } }, "node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==" + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==" }, "node_modules/@types/jest": { "version": "27.5.2", @@ -6293,11 +6485,11 @@ } }, "node_modules/rollup": { - "version": "4.20.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.20.0.tgz", - "integrity": "sha512-6rbWBChcnSGzIlXeIdNIZTopKYad8ZG8ajhl78lGRLsI2rX8IkaotQhVas2Ma+GPxJav19wrSzvRvuiv0YKzWw==", + "version": "4.25.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.25.0.tgz", + "integrity": "sha512-uVbClXmR6wvx5R1M3Od4utyLUxrmOcEm3pAtMphn73Apq19PDtHpgZoEvqH2YnnaNUuvKmg2DgRd2Sqv+odyqg==", "dependencies": { - "@types/estree": "1.0.5" + "@types/estree": "1.0.6" }, "bin": { "rollup": "dist/bin/rollup" @@ -6307,22 +6499,24 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.20.0", - "@rollup/rollup-android-arm64": "4.20.0", - "@rollup/rollup-darwin-arm64": "4.20.0", - "@rollup/rollup-darwin-x64": "4.20.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.20.0", - "@rollup/rollup-linux-arm-musleabihf": "4.20.0", - "@rollup/rollup-linux-arm64-gnu": "4.20.0", - "@rollup/rollup-linux-arm64-musl": "4.20.0", - "@rollup/rollup-linux-powerpc64le-gnu": "4.20.0", - "@rollup/rollup-linux-riscv64-gnu": "4.20.0", - "@rollup/rollup-linux-s390x-gnu": "4.20.0", - "@rollup/rollup-linux-x64-gnu": "4.20.0", - "@rollup/rollup-linux-x64-musl": "4.20.0", - "@rollup/rollup-win32-arm64-msvc": "4.20.0", - "@rollup/rollup-win32-ia32-msvc": "4.20.0", - "@rollup/rollup-win32-x64-msvc": "4.20.0", + "@rollup/rollup-android-arm-eabi": "4.25.0", + "@rollup/rollup-android-arm64": "4.25.0", + "@rollup/rollup-darwin-arm64": "4.25.0", + "@rollup/rollup-darwin-x64": "4.25.0", + "@rollup/rollup-freebsd-arm64": "4.25.0", + "@rollup/rollup-freebsd-x64": "4.25.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.25.0", + "@rollup/rollup-linux-arm-musleabihf": "4.25.0", + "@rollup/rollup-linux-arm64-gnu": "4.25.0", + "@rollup/rollup-linux-arm64-musl": "4.25.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.25.0", + "@rollup/rollup-linux-riscv64-gnu": "4.25.0", + "@rollup/rollup-linux-s390x-gnu": "4.25.0", + "@rollup/rollup-linux-x64-gnu": "4.25.0", + "@rollup/rollup-linux-x64-musl": "4.25.0", + "@rollup/rollup-win32-arm64-msvc": "4.25.0", + "@rollup/rollup-win32-ia32-msvc": "4.25.0", + "@rollup/rollup-win32-x64-msvc": "4.25.0", "fsevents": "~2.3.2" } }, From 2032e248a4f3ebb1825794edf5d54a42a9af2e3f Mon Sep 17 00:00:00 2001 From: Process-ing Date: Sat, 9 Nov 2024 13:52:21 +0000 Subject: [PATCH 08/14] Add WebSocket integration --- package-lock.json | 86 +++++++++++++++++++++++++++++++++++++++++++++++ package.json | 1 + src/api/socket.ts | 73 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 160 insertions(+) create mode 100644 src/api/socket.ts diff --git a/package-lock.json b/package-lock.json index a39122fd..e8e1d14c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -49,6 +49,7 @@ "react-router-dom": "^6.3.0", "react-sortablejs": "^6.1.4", "react-toastify": "^9.1.1", + "socket.io-client": "^4.8.0", "sortablejs": "^1.15.2", "swr": "^2.2.5", "tailwind-merge": "^2.2.0", @@ -2137,6 +2138,12 @@ "node": ">= 14" } }, + "node_modules/@socket.io/component-emitter": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", + "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==", + "license": "MIT" + }, "node_modules/@tailwindcss/forms": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.7.tgz", @@ -3768,6 +3775,28 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/engine.io-client": { + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.1.tgz", + "integrity": "sha512-aYuoak7I+R83M/BBPIOs2to51BmFIpC1wZe6zZzMrT2llVsHy5cvcmdsJgP2Qz6smHu+sD9oexiSUAVd8OfBPw==", + "license": "MIT", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.17.1", + "xmlhttprequest-ssl": "~2.1.1" + } + }, + "node_modules/engine.io-parser": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", + "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/es-define-property": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", @@ -6670,6 +6699,34 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/socket.io-client": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.8.0.tgz", + "integrity": "sha512-C0jdhD5yQahMws9alf/yvtsMGTaIDBnZ8Rb5HU56svyq0l5LIrGzIDZZD5pHQlmzxLuU91Gz+VpQMKgCTNYtkw==", + "license": "MIT", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.2", + "engine.io-client": "~6.6.1", + "socket.io-parser": "~4.2.4" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-parser": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", + "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", + "license": "MIT", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/sortablejs": { "version": "1.15.2", "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.2.tgz", @@ -7695,6 +7752,35 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true }, + "node_modules/ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xmlhttprequest-ssl": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.1.tgz", + "integrity": "sha512-ptjR8YSJIXoA3Mbv5po7RtSYHO6mZr8s7i5VGmEk7QY2pQWyT1o0N+W1gKbOyJPUCGXGnuw0wqe8f0L6Y0ny7g==", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", diff --git a/package.json b/package.json index 31b22fc0..b956abec 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "react-router-dom": "^6.3.0", "react-sortablejs": "^6.1.4", "react-toastify": "^9.1.1", + "socket.io-client": "^4.8.0", "sortablejs": "^1.15.2", "swr": "^2.2.5", "tailwind-merge": "^2.2.0", diff --git a/src/api/socket.ts b/src/api/socket.ts new file mode 100644 index 00000000..3b9b38c9 --- /dev/null +++ b/src/api/socket.ts @@ -0,0 +1,73 @@ +import { io, Socket } from "socket.io-client"; +import backendApi from "./backend"; + +const SOCKET_URL = 'ws://' + backendApi.BACKEND_URL.split('//')[1]; + +class OptionalSocket { + private socket: Socket | null; + + constructor() { + this.socket = null; + } + + set(socket: Socket) { + this.socket = socket; + } + + unset() { + this.socket = null; + } + + use(callback: (socket: Socket) => T): T { + if (!this.socket) { + throw new Error('Socket is not connected'); + } + return callback(this.socket); + } +} + +class SessionsSocket { + private url: string; + private socket: OptionalSocket; + + constructor(url: string) { + this.url = url; + this.socket = new OptionalSocket(); + } + + connect() { + const newSocket = io(this.url, { + auth: { + token: 'dummy', // TODO: Replace with actual federated authentication token + } + }); + this.socket.set(newSocket); + console.log('Connected to socket'); + } + + disconnect() { + this.socket.use(socket => socket.disconnect()); + this.socket.unset(); + + console.log('Disconnected from socket'); + } + + on(event: string, callback: (...args: any[]) => void) { + this.socket.use(socket => socket.on(event, callback)); + } + + off(event: string, callback?: (...args: any[]) => void) { + this.socket.use(socket => socket.off(event, callback)); + } + + emit(event: string, ...args: any[]) { + this.socket.use(socket => socket.emit(event, args)); + } +} + +const sessionsSocket = new SessionsSocket(SOCKET_URL); + +export { + sessionsSocket, + SOCKET_URL, +}; From 49b1afad5763a9f517cbcdd5863d1946d319545d Mon Sep 17 00:00:00 2001 From: Process-ing Date: Sat, 9 Nov 2024 15:58:15 +0000 Subject: [PATCH 09/14] Remove console logs --- src/api/socket.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/api/socket.ts b/src/api/socket.ts index 3b9b38c9..2ad9e109 100644 --- a/src/api/socket.ts +++ b/src/api/socket.ts @@ -42,14 +42,11 @@ class SessionsSocket { } }); this.socket.set(newSocket); - console.log('Connected to socket'); } disconnect() { this.socket.use(socket => socket.disconnect()); this.socket.unset(); - - console.log('Disconnected from socket'); } on(event: string, callback: (...args: any[]) => void) { From 807da66e7277e873736471c8f2b24a579d8bf025 Mon Sep 17 00:00:00 2001 From: Process-ing Date: Sat, 9 Nov 2024 19:39:17 +0000 Subject: [PATCH 10/14] Fix Socket.IO client dependency --- package-lock.json | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/package-lock.json b/package-lock.json index e8e1d14c..ad89c0cd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3715,6 +3715,28 @@ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" }, + "node_modules/engine.io-client": { + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.1.tgz", + "integrity": "sha512-aYuoak7I+R83M/BBPIOs2to51BmFIpC1wZe6zZzMrT2llVsHy5cvcmdsJgP2Qz6smHu+sD9oexiSUAVd8OfBPw==", + "license": "MIT", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.17.1", + "xmlhttprequest-ssl": "~2.1.1" + } + }, + "node_modules/engine.io-parser": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", + "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/es-abstract": { "version": "1.23.3", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", @@ -3775,28 +3797,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/engine.io-client": { - "version": "6.6.1", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.1.tgz", - "integrity": "sha512-aYuoak7I+R83M/BBPIOs2to51BmFIpC1wZe6zZzMrT2llVsHy5cvcmdsJgP2Qz6smHu+sD9oexiSUAVd8OfBPw==", - "license": "MIT", - "dependencies": { - "@socket.io/component-emitter": "~3.1.0", - "debug": "~4.3.1", - "engine.io-parser": "~5.2.1", - "ws": "~8.17.1", - "xmlhttprequest-ssl": "~2.1.1" - } - }, - "node_modules/engine.io-parser": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", - "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", - "license": "MIT", - "engines": { - "node": ">=10.0.0" - } - }, "node_modules/es-define-property": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", From 020dbc86115bca784a2a500a1be7c83083fa506c Mon Sep 17 00:00:00 2001 From: Process-ing Date: Sat, 9 Nov 2024 19:39:46 +0000 Subject: [PATCH 11/14] Make WebSocket URL schema dynamic --- src/api/socket.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/socket.ts b/src/api/socket.ts index 2ad9e109..d516de0d 100644 --- a/src/api/socket.ts +++ b/src/api/socket.ts @@ -1,7 +1,7 @@ import { io, Socket } from "socket.io-client"; import backendApi from "./backend"; -const SOCKET_URL = 'ws://' + backendApi.BACKEND_URL.split('//')[1]; +const SOCKET_URL = (import.meta.env.VITE_APP_PROD == 0 ? 'ws://' : 'wss://') + backendApi.BACKEND_URL.split('//')[1]; class OptionalSocket { private socket: Socket | null; From 8cb93acbd7c4808ddad2c672164bd918d0e5b662 Mon Sep 17 00:00:00 2001 From: racoelhosilva Date: Sun, 17 Nov 2024 12:48:07 +0000 Subject: [PATCH 12/14] feat: added erase button design --- .../planner/sidebar/CoursesController.tsx | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/components/planner/sidebar/CoursesController.tsx b/src/components/planner/sidebar/CoursesController.tsx index 5f3c87f5..a8786582 100644 --- a/src/components/planner/sidebar/CoursesController.tsx +++ b/src/components/planner/sidebar/CoursesController.tsx @@ -1,6 +1,7 @@ import { useContext } from 'react' import ClassSelector from './CoursesController/ClassSelector' import CourseContext from '../../../contexts/CourseContext' +import { TrashIcon } from "@heroicons/react/24/outline" import { NoMajorSelectedSVG } from '../../svgs' import { Button } from '../../ui/button' @@ -9,6 +10,9 @@ const CoursesController = () => { const { pickedCourses, setUcsModalOpen } = useContext(CourseContext); const noCoursesPicked = pickedCourses.length === 0; + + const eraseClasses = () => { }; + return (
{noCoursesPicked ? ( @@ -28,6 +32,20 @@ const CoursesController = () => { )) )} + + {!noCoursesPicked && ( +
+ +
+ )} +
) } From c097e49a05c2e1de49ba3210c18e9d4f1e13c759 Mon Sep 17 00:00:00 2001 From: racoelhosilva Date: Sun, 17 Nov 2024 12:49:13 +0000 Subject: [PATCH 13/14] feat: added eraseClasses logic --- .../planner/sidebar/CoursesController.tsx | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/components/planner/sidebar/CoursesController.tsx b/src/components/planner/sidebar/CoursesController.tsx index a8786582..cc3b076b 100644 --- a/src/components/planner/sidebar/CoursesController.tsx +++ b/src/components/planner/sidebar/CoursesController.tsx @@ -1,6 +1,7 @@ import { useContext } from 'react' import ClassSelector from './CoursesController/ClassSelector' import CourseContext from '../../../contexts/CourseContext' +import MultipleOptionsContext from '../../../contexts/MultipleOptionsContext' import { TrashIcon } from "@heroicons/react/24/outline" import { NoMajorSelectedSVG } from '../../svgs' import { Button } from '../../ui/button' @@ -8,10 +9,26 @@ import { Button } from '../../ui/button' const CoursesController = () => { const { pickedCourses, setUcsModalOpen } = useContext(CourseContext); + const { multipleOptions, selectedOption, setMultipleOptions } = useContext(MultipleOptionsContext); const noCoursesPicked = pickedCourses.length === 0; - const eraseClasses = () => { }; + const eraseClasses = () => { + const currentOption = multipleOptions[selectedOption]; + + const updatedCourseOptions = currentOption.course_options.map(courseOption => ({ + ...courseOption, + picked_class_id: null, + })); + + const updatedMultipleOptions = [...multipleOptions]; + updatedMultipleOptions[selectedOption] = { + ...currentOption, + course_options: updatedCourseOptions, + }; + + setMultipleOptions(updatedMultipleOptions); + }; return (
From c8cd03b5fde3ed9cf88bab8e7d6a030f431b034b Mon Sep 17 00:00:00 2001 From: racoelhosilva Date: Mon, 18 Nov 2024 07:23:12 +0000 Subject: [PATCH 14/14] fix: reset locked state on class erase --- src/components/planner/sidebar/CoursesController.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/planner/sidebar/CoursesController.tsx b/src/components/planner/sidebar/CoursesController.tsx index cc3b076b..6b9322a0 100644 --- a/src/components/planner/sidebar/CoursesController.tsx +++ b/src/components/planner/sidebar/CoursesController.tsx @@ -19,6 +19,7 @@ const CoursesController = () => { const updatedCourseOptions = currentOption.course_options.map(courseOption => ({ ...courseOption, picked_class_id: null, + locked: false, })); const updatedMultipleOptions = [...multipleOptions];