From cf949feeec0c70f18d1bf3a15a94aaa321a120a1 Mon Sep 17 00:00:00 2001 From: Jason De Lanerolle Date: Tue, 19 May 2026 14:48:54 -0400 Subject: [PATCH 01/39] initial changes to Tables + migration script --- app/Database/Migrations.hs | 12 +++++++++++- app/Database/Tables.hs | 13 ++++++------- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/app/Database/Migrations.hs b/app/Database/Migrations.hs index 1ac16ed00..e189dbbd0 100644 --- a/app/Database/Migrations.hs +++ b/app/Database/Migrations.hs @@ -31,7 +31,10 @@ applyMigrations currVersion migrations = do -- | List of migrations migrationList :: [MigrationWrapper] -migrationList = [MigrationWrapper {version=2, script=renamePostTables}] +migrationList = [ + MigrationWrapper {version=2, script=renamePostTables}, + MigrationWrapper {version=3, script=splitTimes} + ] -- | Migration script which renames the Post tables to Program renamePostTables :: Migration @@ -40,6 +43,13 @@ renamePostTables = do addMigration True "ALTER TABLE post_category RENAME TO program_category;" addMigration True "ALTER TABLE program_category RENAME COLUMN post TO program;" +-- | Migration script to add proper support for year-long courses +splitTimes :: Migration +splitTimes = do + addMigration True "ALTER TABLE times RENAME COLUMN first_room TO location;" + addMigration True "ALTER TABLE times DROP COLUMN second_room;" + addMigration True "ALTER TABLE times ADD session varchar(32);" + -- | Gets the current version of the database. -- If no version is defined, initialize the -- version to the latest version and return that. diff --git a/app/Database/Tables.hs b/app/Database/Tables.hs index edc6366c4..5bab8e3a5 100644 --- a/app/Database/Tables.hs +++ b/app/Database/Tables.hs @@ -71,12 +71,12 @@ Meeting UniqueMeeting code session section Times + session T.Text Maybe weekDay Double startHour Double endHour Double meeting MeetingId - firstRoom T.Text Maybe - secondRoom T.Text Maybe + location T.Text Maybe Breadth description T.Text @@ -312,22 +312,21 @@ convertTimeVals _ _ _ = (5.0, 25.0, 25.0) -- | Convert Times into Time buildTime :: Times -> SqlPersistM Time buildTime t = do - room1 <- getBuilding (timesFirstRoom t) - room2 <- getBuilding (timesSecondRoom t) + room1 <- getBuilding (timesLocation t) return $ Time (timesWeekDay t) (timesStartHour t) (timesEndHour t) room1 - room2 + Nothing -- Temporary null data buildTimes :: Key Meeting -> Time' -> Times buildTimes meetingKey t = - Times (weekDay' t) + Times (Just "") -- Temporary null data + (weekDay' t) (startHour' t) (endHour' t) meetingKey (firstLocation' t) - (secondLocation' t) -- | Given a building code, get the persistent Building associated with it getBuilding :: Maybe T.Text -> SqlPersistM (Maybe Building) From f8ea3735f06bf5d2c407cda89d25368ac738e39d Mon Sep 17 00:00:00 2001 From: Jason De Lanerolle Date: Thu, 21 May 2026 16:39:01 -0400 Subject: [PATCH 02/39] changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a52361be..f46458299 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ - Removed `Location` datatype in favour of `Building` - Refactor tests to run directly on tuple input to prevent unnecessary unpacking and repacking - Renamed usages of the word "room" to "location" in the codebase to better reflect the data represented +- Refactor `Times` database schema to encompass only a single session of a course ## [0.7.2] - 2025-12-10 From aa12db7855ba90073a409e9c7c53b829a8522303 Mon Sep 17 00:00:00 2001 From: Rui Weng <109623243+r-weng@users.noreply.github.com> Date: Fri, 22 May 2026 09:47:02 -0400 Subject: [PATCH 03/39] Added tests for JSON parsing of Time' data type (#1706) --- CHANGELOG.md | 1 + README.md | 1 + app/Database/Tables.hs | 2 +- backend-test/Database/TablesTests.hs | 47 ++++++++++++++++++++++++++++ courseography.cabal | 1 + 5 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 backend-test/Database/TablesTests.hs diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a52361be..9bfaa8cc1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ - Removed `Location` datatype in favour of `Building` - Refactor tests to run directly on tuple input to prevent unnecessary unpacking and repacking - Renamed usages of the word "room" to "location" in the codebase to better reflect the data represented +- Added test cases for JSON parsing of Time' data type in `backend-test/Database/TablesTests.hs` ## [0.7.2] - 2025-12-10 diff --git a/README.md b/README.md index 404f4d141..d6f913b18 100644 --- a/README.md +++ b/README.md @@ -143,6 +143,7 @@ Ian Stewart-Binks, Alan Su, Maryam Taj, Betty Wang, +Rui Weng, Fullchee Zhang, Minfan Zhang, Alex Shih, diff --git a/app/Database/Tables.hs b/app/Database/Tables.hs index edc6366c4..3630fdb8d 100644 --- a/app/Database/Tables.hs +++ b/app/Database/Tables.hs @@ -174,7 +174,7 @@ data Time' = endHour' :: Double, firstLocation' :: Maybe T.Text, secondLocation' :: Maybe T.Text - } deriving (Show, Generic) + } deriving (Show, Eq, Generic) data Time = Time { weekDay :: Double, diff --git a/backend-test/Database/TablesTests.hs b/backend-test/Database/TablesTests.hs new file mode 100644 index 000000000..266e6985e --- /dev/null +++ b/backend-test/Database/TablesTests.hs @@ -0,0 +1,47 @@ +{-| +Description: Tables module tests. + +Module that contains the tests for the functions in the Tables module. + +-} + +module Database.TablesTests +( test_tables +) where + +import Data.Aeson (decodeStrictText) +import qualified Data.Text as T +import Database.Tables (Time' (..)) +import Test.Tasty (TestTree, testGroup) +import Test.Tasty.HUnit (assertEqual, testCase) + +-- | List of test cases as (label, input JSON string, expected output) +time'FromJSONTestCases :: [(String, T.Text, Maybe Time')] +time'FromJSONTestCases = + [ ("Empty JSON string, Nothing returned", "", Nothing) + , ("Valid JSON string", "{ \"start\": { \"day\": 1, \"millisofday\": 36000000 }, \"end\": { \"millisofday\": 39600000 }, \"building\": { \"buildingCode\": \"BA\", \"buildingRoomNumber\": \"1130\" }, \"assignedRoom2\": \"MP102\" }", Just (Time' {weekDay' = 0.0, startHour' = 10.0, endHour' = 11.0, firstLocation' = Just "BA1130", secondLocation' = Just "MP102"})) + , ("Valid JSON string with no assignedRoom2", "{ \"start\": { \"day\": 2, \"millisofday\": 39600000 }, \"end\": { \"millisofday\": 43200000 }, \"building\": { \"buildingCode\": \"MP\", \"buildingRoomNumber\": \"203\" } }", Just (Time' {weekDay' = 1.0, startHour' = 11.0, endHour' = 12.0, firstLocation' = Just "MP203", secondLocation' = Nothing})) + , ("Valid JSON string with no day, default time values returned", "{ \"start\": { \"millisofday\": 43200000 }, \"end\": { \"millisofday\": 50400000 }, \"building\": { \"buildingCode\": \"MY\", \"buildingRoomNumber\": \"150\" } }", Just (Time' {weekDay' = 5.0, startHour' = 25.0, endHour' = 25.0, firstLocation' = Just "MY150", secondLocation' = Nothing})) + , ("Valid JSON string with no start millisofday, default time values returned", "{ \"start\": { \"day\": 3 }, \"end\": { \"millisofday\": 50400000 }, \"building\": { \"buildingCode\": \"MY\", \"buildingRoomNumber\": \"150\" } }", Just (Time' {weekDay' = 5.0, startHour' = 25.0, endHour' = 25.0, firstLocation' = Just "MY150", secondLocation' = Nothing})) + , ("Valid JSON string with no end millisofday, default time values returned", "{ \"start\": { \"day\": 3, \"millisofday\": 43200000 }, \"end\": { }, \"building\": { \"buildingCode\": \"MY\", \"buildingRoomNumber\": \"150\" } }", Just (Time' {weekDay' = 5.0, startHour' = 25.0, endHour' = 25.0, firstLocation' = Just "MY150", secondLocation' = Nothing})) + , ("Invalid JSON string with no start value, Nothing returned", "{ \"end\": { \"millisofday\": 54000000 }, \"building\": { \"buildingCode\": \"MP\", \"buildingRoomNumber\": \"202\" } }", Nothing) + , ("Invalid JSON string with no end value, Nothing returned", "{ \"start\": { \"day\": 4, \"millisofday\": 50400000 }, \"building\": { \"buildingCode\": \"MP\", \"buildingRoomNumber\": \"202\" } }", Nothing) + , ("Invalid JSON string with no buildingCode value, Nothing returned", "{ \"start\": { \"day\": 4, \"millisofday\": 50400000 }, \"end\": { \"millisofday\": 54000000 }, \"building\": { \"buildingRoomNumber\": \"202\" } }", Nothing) + , ("Invalid JSON string with no buildingRoomNumber value, Nothing returned", "{ \"start\": { \"day\": 4, \"millisofday\": 50400000 }, \"end\": { \"millisofday\": 54000000 }, \"building\": { \"buildingCode\": \"MP\" } }", Nothing) + ] + +-- | Run a test case (label, input JSON string, expected output) on the FromJSON instance of Time'. +runTime'FromJSONTest :: (String, T.Text, Maybe Time') -> TestTree +runTime'FromJSONTest (label, input, expected) = + testCase label $ do + let decoded = decodeStrictText input :: Maybe Time' + assertEqual ("Unexpected parsing result for " ++ label) expected decoded + +-- | Run all the time'FromJSON test cases +runTime'FromJSONTests :: [TestTree] +runTime'FromJSONTests = map runTime'FromJSONTest time'FromJSONTestCases + +-- | Test suite for Tables Module +test_tables :: TestTree +test_tables = + testGroup "Tables tests" runTime'FromJSONTests diff --git a/courseography.cabal b/courseography.cabal index 653527376..0d4179fdd 100644 --- a/courseography.cabal +++ b/courseography.cabal @@ -120,6 +120,7 @@ test-suite Tests Controllers.GraphControllerTests, Controllers.ProgramControllerTests, Database.CourseQueriesTests, + Database.TablesTests, RequirementTests.ModifierTests, RequirementTests.PostParserTests, RequirementTests.PreProcessingTests, From e21e0842ecb12245f8a7137ae12d235438ca6890 Mon Sep 17 00:00:00 2001 From: Angelina Jiang <43974738+AngelsandDevsLOL@users.noreply.github.com> Date: Fri, 22 May 2026 10:47:18 -0400 Subject: [PATCH 04/39] Add tests for Database.Tables FromJSON Meeting instance (#1707) --- CHANGELOG.md | 1 + README.md | 1 + app/Database/Tables.hs | 2 +- backend-test/Database/TablesTests.hs | 32 +++++++++++++++++++++++++--- 4 files changed, 32 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9bfaa8cc1..44894175e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ - Removed `Location` datatype in favour of `Building` - Refactor tests to run directly on tuple input to prevent unnecessary unpacking and repacking - Renamed usages of the word "room" to "location" in the codebase to better reflect the data represented +- Added test cases for JSON parsing of Meeting data type in `backend-test/Database/TablesTests.hs` - Added test cases for JSON parsing of Time' data type in `backend-test/Database/TablesTests.hs` ## [0.7.2] - 2025-12-10 diff --git a/README.md b/README.md index d6f913b18..cdd02a22e 100644 --- a/README.md +++ b/README.md @@ -120,6 +120,7 @@ Nazanin Ghazitabatabai, Sidharth Gupta, Parker Hutcheson, Yoonie Jang, +Angelina Jiang, Jai Joshi, Aayush Karki, Japleen Kaur, diff --git a/app/Database/Tables.hs b/app/Database/Tables.hs index 3630fdb8d..fe5c631e6 100644 --- a/app/Database/Tables.hs +++ b/app/Database/Tables.hs @@ -67,7 +67,7 @@ Meeting enrol Int wait Int extra Int - deriving Generic Show + deriving Generic Show Eq UniqueMeeting code session section Times diff --git a/backend-test/Database/TablesTests.hs b/backend-test/Database/TablesTests.hs index 266e6985e..bac1db7c0 100644 --- a/backend-test/Database/TablesTests.hs +++ b/backend-test/Database/TablesTests.hs @@ -9,12 +9,38 @@ module Database.TablesTests ( test_tables ) where -import Data.Aeson (decodeStrictText) +import Data.Aeson (decode, decodeStrictText) +import qualified Data.ByteString.Lazy.Char8 as BL import qualified Data.Text as T -import Database.Tables (Time' (..)) +import Database.Tables (Meeting (..), Time' (..)) import Test.Tasty (TestTree, testGroup) import Test.Tasty.HUnit (assertEqual, testCase) +-- | List of test cases as (label, input JSON payload, expected output) +meetingFromJSONTestCases :: [(String, BL.ByteString, Maybe Meeting)] +meetingFromJSONTestCases = + [ ("Invalid meeting (empty JSON), Nothing returned", "{}", Nothing) + , ("Valid meeting with valid teachMethod", "{\"teachMethod\":\"LEC\"}", Just (Meeting "" "" "LEC" (-1) "" 0 0 0)) + , ("Valid meeting with all fields", "{\"teachMethod\":\"LEC\",\"sectionNumber\":\"0101\",\"maxEnrolment\":100,\"currentEnrolment\":77,\"currentWaitlist\":0,\"instructors\":[{\"firstName\":\"Brinda\",\"lastName\":\"Venkataramani\"}]}", Just (Meeting "" "" "LEC0101" 100 "Brinda. Venkataramani" 77 0 0)) + , ("Valid meeting with no maxEnrolment, default cap returned", "{\"teachMethod\":\"LEC\",\"sectionNumber\":\"0101\"}", Just (Meeting "" "" "LEC0101" (-1) "" 0 0 0)) + , ("Valid meeting with no currentEnrolment, default enrol returned", "{\"teachMethod\":\"LEC\",\"sectionNumber\":\"0101\",\"maxEnrolment\":100}", Just (Meeting "" "" "LEC0101" 100 "" 0 0 0)) + , ("Valid meeting with no currentWaitlist, default wait returned", "{\"teachMethod\":\"LEC\",\"sectionNumber\":\"0101\",\"maxEnrolment\":100,\"currentEnrolment\":50}", Just (Meeting "" "" "LEC0101" 100 "" 50 0 0)) + , ("Valid meeting with multiple instructors", "{\"teachMethod\":\"LEC\",\"sectionNumber\":\"0101\",\"instructors\":[{\"firstName\":\"A\",\"lastName\":\"B\"},{\"firstName\":\"C\",\"lastName\":\"D\"}]}", Just (Meeting "" "" "LEC0101" (-1) "A. B; C. D" 0 0 0)) + , ("Invalid meeting with no teachMethod, Nothing returned", "{\"sectionNumber\":\"0101\",\"maxEnrolment\":100}", Nothing) + , ("Invalid meeting with unknown teachMethod, Nothing returned", "{\"teachMethod\":\"LAB\",\"sectionNumber\":\"0101\"}", Nothing) + ] + +-- | Run a test case (case, input, expected output) on the FromJSON instance of Meeting. +runMeetingFromJSONTest :: (String, BL.ByteString, Maybe Meeting) -> TestTree +runMeetingFromJSONTest (label, meetingJSON, expected) = + testCase label $ do + let actual = decode meetingJSON :: Maybe Meeting + assertEqual ("Unexpected parsing result for " ++ label) expected actual + +-- | Run all the meetingFromJSON test cases +runMeetingFromJSONTests :: [TestTree] +runMeetingFromJSONTests = map runMeetingFromJSONTest meetingFromJSONTestCases + -- | List of test cases as (label, input JSON string, expected output) time'FromJSONTestCases :: [(String, T.Text, Maybe Time')] time'FromJSONTestCases = @@ -44,4 +70,4 @@ runTime'FromJSONTests = map runTime'FromJSONTest time'FromJSONTestCases -- | Test suite for Tables Module test_tables :: TestTree test_tables = - testGroup "Tables tests" runTime'FromJSONTests + testGroup "Tables tests" $ runMeetingFromJSONTests ++ runTime'FromJSONTests From 3a2ebe7cf544b8ad44c1ac88552180e7fe2a94c8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 30 May 2026 07:31:22 -0400 Subject: [PATCH 05/39] build(deps): bump tmp from 0.2.5 to 0.2.7 (#1717) Bumps [tmp](https://github.com/raszi/node-tmp) from 0.2.5 to 0.2.7. - [Changelog](https://github.com/raszi/node-tmp/blob/master/CHANGELOG.md) - [Commits](https://github.com/raszi/node-tmp/compare/v0.2.5...v0.2.7) --- updated-dependencies: - dependency-name: tmp dependency-version: 0.2.7 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index be763301a..5fb9bd050 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12725,9 +12725,9 @@ __metadata: linkType: hard "tmp@npm:~0.2.3": - version: 0.2.5 - resolution: "tmp@npm:0.2.5" - checksum: 9d18e58060114154939930457b9e198b34f9495bcc05a343bc0a0a29aa546d2c1c2b343dae05b87b17c8fde0af93ab7d8fe8574a8f6dc2cd8fd3f2ca1ad0d8e1 + version: 0.2.7 + resolution: "tmp@npm:0.2.7" + checksum: 45dec2fc288ad368eeff7268cb6d5d33452c6d35f4f7d9b1b5e023409a141dab57a3c08b5f505daf3af6d69667a5f544fc1a5b6a27c6f9396a5a1b4002912f1c languageName: node linkType: hard From bc71bea63d57dbb96bc403bcf00794baff26fc39 Mon Sep 17 00:00:00 2001 From: Rui Weng <109623243+r-weng@users.noreply.github.com> Date: Sun, 31 May 2026 10:24:27 -0400 Subject: [PATCH 06/39] Refactored graph helper functions from Svg.Database to Models.Graph (#1716) --- CHANGELOG.md | 2 ++ app/Models/Graph.hs | 38 +++++++++++++++++++++++++++++++++----- app/Svg/Builder.hs | 2 +- app/Svg/Database.hs | 40 ---------------------------------------- app/Svg/Parser.hs | 38 ++++++-------------------------------- app/Util/Blaze.hs | 2 +- app/Util/Matrix.hs | 26 ++++++++++++++++++++++++++ courseography.cabal | 4 ++-- 8 files changed, 71 insertions(+), 81 deletions(-) delete mode 100644 app/Svg/Database.hs create mode 100644 app/Util/Matrix.hs diff --git a/CHANGELOG.md b/CHANGELOG.md index 44894175e..d22a1d88c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,8 @@ - Renamed usages of the word "room" to "location" in the codebase to better reflect the data represented - Added test cases for JSON parsing of Meeting data type in `backend-test/Database/TablesTests.hs` - Added test cases for JSON parsing of Time' data type in `backend-test/Database/TablesTests.hs` +- Refactor graph helper functions from `app/Svg/Database.hs` to `app/Models/Graph.hs` +- Refactor functions for performing matrix operations from `app/Svg/Parser.hs` to `app/Util/Matrix.hs` ## [0.7.2] - 2025-12-10 diff --git a/app/Models/Graph.hs b/app/Models/Graph.hs index 6b611b2f7..29e4dcf3d 100644 --- a/app/Models/Graph.hs +++ b/app/Models/Graph.hs @@ -1,14 +1,13 @@ module Models.Graph - (getGraph, - insertGraph) where + (getGraph, insertGraph, insertElements, deleteExistingGraph) where import Config (runDb) import Data.Aeson (Value, object, toJSON) import qualified Data.Text as T (Text) import Database.DataType (ShapeType (BoolNode, Hybrid, Node)) import Database.Persist.Sqlite (Entity, PersistEntity, PersistValue (PersistInt64), SqlPersistM, - entityKey, entityVal, insert, insertMany_, keyToValues, selectFirst, - selectList, (<-.), (==.)) + deleteWhere, entityKey, entityVal, insert, insert_, insertMany_, keyToValues, + selectFirst, selectList, (<-.), (==.)) import Database.Tables hiding (paths, shapes, texts) import Svg.Builder (buildEllipses, buildPath, buildRect) import Util.Helpers @@ -54,9 +53,38 @@ getGraph graphName = runDb $ do return (Just response) -insertGraph :: T.Text -> SvgJSON -> SqlPersistM () +-- | Insert a new graph into the database, given its SVG JSON. +-- | Return Nothing. +insertGraph :: T.Text -- ^ The title of the graph being inserted. + -> SvgJSON -- ^ The SVG JSON data of the inserted graph (texts, shapes, paths). + -> SqlPersistM () -- ^ Return Nothing. insertGraph nameStr_ (SvgJSON texts shapes paths) = do gId <- insert $ Graph nameStr_ 256 256 False insertMany_ $ map (\text -> text {textGraph = gId}) texts insertMany_ $ map (\shape -> shape {shapeGraph = gId}) shapes insertMany_ $ map (\path -> path {pathGraph = gId}) paths + +-- | Insert graph components into the database. +insertElements :: ([Path], [Shape], [Text]) -> SqlPersistM () +insertElements (paths, shapes, texts) = do + mapM_ insert_ shapes + mapM_ insert_ paths + mapM_ insert_ texts + +-- | Delete the graph with the given name from the database, if it exists. +deleteExistingGraph :: T.Text -> SqlPersistM () +deleteExistingGraph graphName = do + graphEnt :: (Maybe (Entity Graph)) <- selectFirst [GraphTitle ==. graphName] [] + case graphEnt of + Just graph -> do + let gId = entityKey graph + deleteGraph gId + Nothing -> pure () + +-- | Delete a graph with the given graph ID from the database. +deleteGraph :: Key Graph -> SqlPersistM () +deleteGraph gId = do + deleteWhere [TextGraph ==. gId] + deleteWhere [ShapeGraph ==. gId] + deleteWhere [PathGraph ==. gId] + deleteWhere [GraphId ==. gId] diff --git a/app/Svg/Builder.hs b/app/Svg/Builder.hs index aa68ca4ca..cd5a51f2f 100644 --- a/app/Svg/Builder.hs +++ b/app/Svg/Builder.hs @@ -22,7 +22,7 @@ import Data.List (find) import qualified Data.Text as T import Database.DataType import Database.Tables hiding (shapes, texts) -import Svg.Parser (matrixPointMultiply) +import Util.Matrix (matrixPointMultiply) import TextShow (showt) import Util.Helpers diff --git a/app/Svg/Database.hs b/app/Svg/Database.hs deleted file mode 100644 index c36061000..000000000 --- a/app/Svg/Database.hs +++ /dev/null @@ -1,40 +0,0 @@ -{-| -Description: Helpers for interacting with the graph database. Incomplete. - -This module is responsible for inserting values associated with the graphs -into the database. These functions are just helpers for the main function -in "Svg.Parser", though it is possible to put all of the data retrieval code in -here as well at some point in the future. --} - -module Svg.Database - (insertGraph, insertElements, deleteGraph) where - -import qualified Data.Text as T -import Database.Persist.Sqlite -import Database.Tables hiding (graphDynamic, graphHeight, graphWidth, paths, shapes, texts) - --- | Insert a new graph into the database, returning the key of the new graph. -insertGraph :: T.Text -- ^ The title of the graph that is being inserted. - -> Double -- ^ The width dimension of the graph - -> Double -- ^ The height dimension of the graph - -> Bool -- ^ True if graph is dynamically generated - -> SqlPersistM GraphId -- ^ The unique identifier of the inserted graph. -insertGraph graphName graphWidth graphHeight graphDynamic = do - runMigration migrateAll - insert (Graph graphName graphWidth graphHeight graphDynamic) - --- | Insert graph components into the database. -insertElements :: ([Path], [Shape], [Text]) -> SqlPersistM () -insertElements (paths, shapes, texts) = do - mapM_ insert_ shapes - mapM_ insert_ paths - mapM_ insert_ texts - --- | Delete a graph with the given graph ID from the database. -deleteGraph :: Key Graph -> SqlPersistM () -deleteGraph gId = do - deleteWhere [TextGraph ==. gId] - deleteWhere [ShapeGraph ==. gId] - deleteWhere [PathGraph ==. gId] - deleteWhere [GraphId ==. gId] diff --git a/app/Svg/Parser.hs b/app/Svg/Parser.hs index bfe4ae12d..a9be16f3b 100644 --- a/app/Svg/Parser.hs +++ b/app/Svg/Parser.hs @@ -5,7 +5,7 @@ This module is reponsible for parsing the SVG files exported from Inkscape. It also currently acts as a main driver for the whole graph pipeline: 1. Parsing the raw SVG files -2. Inserting them into the database (see "Svg.Database") +2. Inserting them into the database (see "Models.Graph") 3. Retrieving the database values and generating a new SVG file (See "Svg.Builder" and "Svg.Generator") @@ -14,19 +14,19 @@ directly to the client when viewing the @/graph@ page. -} module Svg.Parser - (parsePrebuiltSvgs, parseDynamicSvg, matrixPointMultiply) where + (parsePrebuiltSvgs, parseDynamicSvg) where import Config (graphPath, runDb) import Control.Monad.IO.Class (liftIO) import Data.Char (isSpace) -import Data.List as List +import qualified Data.List as List import Data.Maybe (fromMaybe) import qualified Data.Text as T import Data.Text.IO as T (readFile) import Database.DataType import Database.Persist.Sqlite import Database.Tables hiding (graphHeight, graphWidth, paths, shapes, texts) -import Svg.Database (deleteGraph, insertElements, insertGraph) +import Models.Graph (deleteExistingGraph, insertElements) import qualified Text.HTML.TagSoup as TS hiding (fromAttrib) import Text.HTML.TagSoup (Tag) import qualified Text.Parsec as P @@ -34,6 +34,7 @@ import Text.Parsec ((<|>)) import Text.Parsec.String (Parser) import Text.Read (readMaybe) import Util.Helpers +import Util.Matrix (matrixMultiply) parsePrebuiltSvgs :: IO () @@ -76,22 +77,12 @@ performParse graphName inputFilename = do graphFile <- liftIO $ T.readFile (gPath ++ inputFilename) performParseFromMemory graphName graphFile False --- | Deletes the graph with the given name from the database if it exists. -deleteExistingGraph :: T.Text -> SqlPersistM () -deleteExistingGraph graphName = do - graphEnt :: (Maybe (Entity Graph)) <- selectFirst [GraphTitle ==. graphName] [] - case graphEnt of - Just graph -> do - let gId = entityKey graph - deleteGraph gId - Nothing -> pure () - performParseFromMemory :: T.Text -- ^ The title of the graph -> T.Text -- ^ Filename of the SVG to parse -> Bool -- ^ True if SVG is dynamically generated -> SqlPersistM () performParseFromMemory graphName graphSvg isDynamic = do - key <- insertGraph graphName graphWidth graphHeight isDynamic + key <- insert (Graph graphName graphWidth graphHeight isDynamic) let parsedGraph = parseSvg key graphSvg insertElements parsedGraph where (graphWidth, graphHeight) = parseSizeFromSvg graphSvg @@ -668,23 +659,6 @@ updateShape fill r = addTuples :: Point -> Point -> Point addTuples (a,b) (c,d) = (a + c, b + d) --- | Apply a matrix transformation to a point. --- The matrix must have dimensions 3x3, representing a transformation for a two-dimensional point, --- i.e., the transformation in the z-component is ignored, so the third row is expected to be [0,0,1] -matrixPointMultiply :: Matrix -> Point -> Point -matrixPointMultiply matrix (x, y) = - case matrix of - [[a, b, tx], [c, d, ty], _] -> (a * x + b * y + tx, c * x + d * y + ty) - _ -> error "Matrix must be 3x3 for point transformation." - --- | Multiplies two 3x3 matrices together. -matrixMultiply :: Matrix -> Matrix -> Matrix -matrixMultiply m1 m2 = [[dotProduct row col | col <- transpose m2] | row <- m1] - --- | Computes the dot product of two vectors. -dotProduct :: Vector -> Vector -> Double -dotProduct v1 v2 = sum $ zipWith (*) v1 v2 - -- | Helper to remove leading and trailing whitespace. trim :: T.Text -> T.Text trim = f . f diff --git a/app/Util/Blaze.hs b/app/Util/Blaze.hs index 0e1193c25..6545927c3 100644 --- a/app/Util/Blaze.hs +++ b/app/Util/Blaze.hs @@ -30,7 +30,7 @@ toLink :: T.Text -> T.Text -> H.Html toLink link content = H.a ! A.href (H.textValue link) $ H.toHtml content --- | mdToHTML takes in the contents of a file written in Mark Down and converts it to +-- |mdToHTML takes in the contents of a file written in Mark Down and converts it to -- blaze-HTML. mdToHTML :: Text -> H.Html mdToHTML = markdown def diff --git a/app/Util/Matrix.hs b/app/Util/Matrix.hs new file mode 100644 index 000000000..d289906ad --- /dev/null +++ b/app/Util/Matrix.hs @@ -0,0 +1,26 @@ +{-| + Module : Util.Matrix + Description : Contains functions for performing matrix operations. +-} + +module Util.Matrix (matrixPointMultiply, matrixMultiply, dotProduct) where + +import Database.Tables (Matrix, Point, Vector) +import Data.List (transpose) + +-- | Apply a matrix transformation to a point. +-- The matrix must have dimensions 3x3, representing a transformation for a two-dimensional point, +-- i.e., the transformation in the z-component is ignored, so the third row is expected to be [0,0,1] +matrixPointMultiply :: Matrix -> Point -> Point +matrixPointMultiply matrix (x, y) = + case matrix of + [[a, b, tx], [c, d, ty], _] -> (a * x + b * y + tx, c * x + d * y + ty) + _ -> error "Matrix must be 3x3 for point transformation." + +-- | Multiplies two 3x3 matrices together. +matrixMultiply :: Matrix -> Matrix -> Matrix +matrixMultiply m1 m2 = [[dotProduct row col | col <- transpose m2] | row <- m1] + +-- | Computes the dot product of two vectors. +dotProduct :: Vector -> Vector -> Double +dotProduct v1 v2 = sum $ zipWith (*) v1 v2 diff --git a/courseography.cabal b/courseography.cabal index 0d4179fdd..1d3111f62 100644 --- a/courseography.cabal +++ b/courseography.cabal @@ -49,12 +49,12 @@ library Models.Program, Scripts, Svg.Builder, - Svg.Database, Svg.Generator, Svg.Parser, Util.Blaze, Util.Happstack, Util.Helpers, + Util.Matrix, WebParsing.ArtSciParser, WebParsing.ParsecCombinators, WebParsing.PostParser, @@ -201,13 +201,13 @@ executable courseography Scripts, Server, Svg.Builder, - Svg.Database, Svg.Generator, Svg.Parser, Util.Blaze, Util.Documentation, Util.Happstack, Util.Helpers, + Util.Matrix, WebParsing.ArtSciParser, WebParsing.Ligature, WebParsing.ParsecCombinators, From 61112ab775894904ec6a829c075e5ad78260a091 Mon Sep 17 00:00:00 2001 From: Rui Weng <109623243+r-weng@users.noreply.github.com> Date: Sun, 31 May 2026 10:35:31 -0400 Subject: [PATCH 07/39] Updated documentation in Util.Blaze (#1719) --- CHANGELOG.md | 1 + app/Util/Blaze.hs | 13 ++++++------- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d22a1d88c..f31197266 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,7 @@ - Added test cases for JSON parsing of Time' data type in `backend-test/Database/TablesTests.hs` - Refactor graph helper functions from `app/Svg/Database.hs` to `app/Models/Graph.hs` - Refactor functions for performing matrix operations from `app/Svg/Parser.hs` to `app/Util/Matrix.hs` +- Updated documentation in `app/Util/Blaze.hs` ## [0.7.2] - 2025-12-10 diff --git a/app/Util/Blaze.hs b/app/Util/Blaze.hs index 6545927c3..7084c803f 100644 --- a/app/Util/Blaze.hs +++ b/app/Util/Blaze.hs @@ -1,6 +1,6 @@ {-| - Module : Util.Blaze - Description : Contains methods for setting various HTML attributes. + Module : Util.Blaze + Description : Contains functions for setting various HTML attributes. -} module Util.Blaze (toStylesheet, @@ -15,22 +15,21 @@ import qualified Text.Blaze.Html5 as H import qualified Text.Blaze.Html5.Attributes as A import Text.Markdown (def, markdown) --- |Sets the html attributes to the href of the style sheet. +-- | Set the HTML attributes to the href of the style sheet. toStylesheet :: T.Text -> H.Html toStylesheet href = H.link ! A.rel "stylesheet" ! A.type_ "text/css" ! A.href (H.textValue href) --- |Sets the script attributes. +-- | Set the script attributes. toScript :: T.Text -> H.Html toScript src = H.script ! A.src (H.textValue src) $ "" --- |Creates a link by setting the href attribute. +-- | Create a link by setting the href attribute. toLink :: T.Text -> T.Text -> H.Html toLink link content = H.a ! A.href (H.textValue link) $ H.toHtml content --- |mdToHTML takes in the contents of a file written in Mark Down and converts it to --- blaze-HTML. +-- | Convert the contents of a markdown file to blaze-HTML. mdToHTML :: Text -> H.Html mdToHTML = markdown def From 4921e7cb97eb94813d5b2baabf8cf4df686a5142 Mon Sep 17 00:00:00 2001 From: Angelina Jiang <43974738+AngelsandDevsLOL@users.noreply.github.com> Date: Tue, 2 Jun 2026 07:55:28 -0400 Subject: [PATCH 08/39] Refactored Building and Time functions into Models (#1718) --- CHANGELOG.md | 1 + app/Controllers/Timetable.hs | 1 + app/Database/Tables.hs | 34 ----------- app/Models/Building.hs | 55 +++++++++++++++++ app/Models/Meeting.hs | 1 + app/Models/Time.hs | 26 ++++++++ app/WebParsing/ArtSciParser.hs | 38 +----------- app/WebParsing/UtsgJsonParser.hs | 3 +- .../Controllers/CourseControllerTests.hs | 4 +- backend-test/Database/BuildingTests.hs | 60 +++++++++++++++++++ courseography.cabal | 5 ++ 11 files changed, 156 insertions(+), 72 deletions(-) create mode 100644 app/Models/Building.hs create mode 100644 app/Models/Time.hs create mode 100644 backend-test/Database/BuildingTests.hs diff --git a/CHANGELOG.md b/CHANGELOG.md index f31197266..147c98d38 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ - Renamed usages of the word "room" to "location" in the codebase to better reflect the data represented - Added test cases for JSON parsing of Meeting data type in `backend-test/Database/TablesTests.hs` - Added test cases for JSON parsing of Time' data type in `backend-test/Database/TablesTests.hs` +- Refactored functions relating to `Building` and `Time` into `Models/Building` and `Models/Time` respectively - Refactor graph helper functions from `app/Svg/Database.hs` to `app/Models/Graph.hs` - Refactor functions for performing matrix operations from `app/Svg/Parser.hs` to `app/Util/Matrix.hs` - Updated documentation in `app/Util/Blaze.hs` diff --git a/app/Controllers/Timetable.hs b/app/Controllers/Timetable.hs index 9763698f4..670338d80 100644 --- a/app/Controllers/Timetable.hs +++ b/app/Controllers/Timetable.hs @@ -21,6 +21,7 @@ import Export.PdfGenerator import Happstack.Server import MasterTemplate import Models.Meeting (returnMeeting) +import Models.Time (buildTime) import Scripts import System.FilePath (()) import System.IO.Temp (withSystemTempDirectory) diff --git a/app/Database/Tables.hs b/app/Database/Tables.hs index fe5c631e6..ef7061472 100644 --- a/app/Database/Tables.hs +++ b/app/Database/Tables.hs @@ -26,7 +26,6 @@ import Data.Char (toLower) import qualified Data.Text as T import Data.Time.Clock (UTCTime) import Database.DataType -import Database.Persist.Sqlite (Key, SqlPersistM, entityVal, selectFirst, (==.)) import Database.Persist.TH import GHC.Generics @@ -308,36 +307,3 @@ convertTimeVals (Just day) (Just start) (Just end) = endDbl = getHourVal end in (dayDbl, startDbl, endDbl) convertTimeVals _ _ _ = (5.0, 25.0, 25.0) - --- | Convert Times into Time -buildTime :: Times -> SqlPersistM Time -buildTime t = do - room1 <- getBuilding (timesFirstRoom t) - room2 <- getBuilding (timesSecondRoom t) - return $ Time (timesWeekDay t) - (timesStartHour t) - (timesEndHour t) - room1 - room2 - -buildTimes :: Key Meeting -> Time' -> Times -buildTimes meetingKey t = - Times (weekDay' t) - (startHour' t) - (endHour' t) - meetingKey - (firstLocation' t) - (secondLocation' t) - --- | Given a building code, get the persistent Building associated with it -getBuilding :: Maybe T.Text -> SqlPersistM (Maybe Building) -getBuilding rm = do - case rm of - Nothing -> return Nothing - Just r -> do - maybeEntityBuilding <- selectFirst [BuildingCode ==. T.take 2 r] [] - case maybeEntityBuilding of - Nothing -> return Nothing - Just entBuilding -> do - let building = entityVal entBuilding - return $ Just building diff --git a/app/Models/Building.hs b/app/Models/Building.hs new file mode 100644 index 000000000..0c2557178 --- /dev/null +++ b/app/Models/Building.hs @@ -0,0 +1,55 @@ +module Models.Building + (buildingsCSV, + parseBuildings, + getBuildingsFromCSV, + getBuilding) where + +import Config (runDb) +import Control.Monad.IO.Class (liftIO) +import Data.CSV (csvFile) +import qualified Data.Text as T +import Database.Persist.Sqlite (Filter, SqlPersistM, deleteWhere, entityVal, insertMany_, + selectFirst, (==.)) +import Database.Tables (Building (Building), EntityField (BuildingCode)) +import Filesystem.Path.CurrentOS as Path (append, decodeString, encodeString) +import System.Directory (getCurrentDirectory) +import Text.ParserCombinators.Parsec (parseFromFile) +import Util.Helpers (safeHead) + +buildingsCSV :: IO Prelude.FilePath +buildingsCSV = do + curDir <- getCurrentDirectory + return $ Path.encodeString $ Path.append (Path.decodeString curDir) $ Path.append (Path.decodeString "db") (Path.decodeString "building.csv") + +parseBuildings :: IO () +parseBuildings = do + buildingInfo <- getBuildingsFromCSV =<< buildingsCSV + runDb $ do + liftIO $ putStrLn "Inserting buildings" + deleteWhere ([] :: [Filter Building]) :: SqlPersistM () + insertMany_ buildingInfo :: SqlPersistM () + +-- | Extract building names, codes, addresses, postal codes, latitude and longitude from csv file +getBuildingsFromCSV :: String -> IO [Building] +getBuildingsFromCSV buildingCSVFile = do + buildingCSVData <- parseFromFile csvFile buildingCSVFile + case buildingCSVData of + Left _ -> error "csv parse error" + Right buildingData -> + return $ map (\b -> Building (T.pack $ safeHead "" b) + (T.pack (b !! 1)) + (T.pack (b !! 2)) + (T.pack (b !! 3)) + (read (b !! 4) :: Double) + (read (b !! 5) :: Double)) $ drop 1 buildingData + +-- | Given a building code, get the persistent Building associated with it +getBuilding :: Maybe T.Text -> SqlPersistM (Maybe Building) +getBuilding rm = + case rm of + Nothing -> return Nothing + Just r -> do + maybeEntityBuilding <- selectFirst [BuildingCode ==. T.take 2 r] [] + case maybeEntityBuilding of + Nothing -> return Nothing + Just entBuilding -> return $ Just (entityVal entBuilding) diff --git a/app/Models/Meeting.hs b/app/Models/Meeting.hs index 05678018b..86f536214 100644 --- a/app/Models/Meeting.hs +++ b/app/Models/Meeting.hs @@ -10,6 +10,7 @@ import qualified Data.Text as T (Text, append, isPrefixOf, tail, take, toUpper) import Database.Persist.Sqlite (Entity, SqlPersistM, entityKey, entityVal, selectFirst, selectList, (<-.), (==.)) import Database.Tables as Tables +import Models.Time (buildTime) -- | Queries the database for all matching lectures, tutorials, meetingQuery :: [T.Text] -> SqlPersistM [MeetTime'] diff --git a/app/Models/Time.hs b/app/Models/Time.hs new file mode 100644 index 000000000..9be774f5e --- /dev/null +++ b/app/Models/Time.hs @@ -0,0 +1,26 @@ +module Models.Time + (buildTime, + buildTimes) where +import Database.Persist.Sqlite (SqlPersistM) +import Database.Tables (MeetingId, Time (..), Time' (..), Times (..)) +import Models.Building (getBuilding) + +-- | Convert a Times record into a Time by resolving room codes to Buildings +buildTime :: Times -> SqlPersistM Time +buildTime t = do + room1 <- getBuilding (timesFirstRoom t) + room2 <- getBuilding (timesSecondRoom t) + return $ Time (timesWeekDay t) + (timesStartHour t) + (timesEndHour t) + room1 + room2 + +buildTimes :: MeetingId -> Time' -> Times +buildTimes meetingKey t = + Times (weekDay' t) + (startHour' t) + (endHour' t) + meetingKey + (firstLocation' t) + (secondLocation' t) diff --git a/app/WebParsing/ArtSciParser.hs b/app/WebParsing/ArtSciParser.hs index 806a220b8..74f5b36ab 100644 --- a/app/WebParsing/ArtSciParser.hs +++ b/app/WebParsing/ArtSciParser.hs @@ -3,27 +3,23 @@ module WebParsing.ArtSciParser import Config (fasCalendarUrl, programsUrl, runDb) import Control.Monad.IO.Class (liftIO) -import Data.CSV import Data.List (findIndex, nubBy) import Data.Maybe (fromMaybe, mapMaybe) import qualified Data.Text as T import Data.Text.Lazy (toStrict) import Data.Text.Lazy.Encoding (decodeUtf8) import Database.Persist (insertUnique) -import Database.Persist.Sqlite (Filter, SqlPersistM, deleteWhere, insertMany_) -import Database.Tables (Building (..), Courses (..), Department (..)) -import Filesystem.Path.CurrentOS as Path +import Database.Persist.Sqlite (SqlPersistM) +import Database.Tables (Courses (..), Department (..)) +import Models.Building (parseBuildings) import Models.Course (insertCourse) import Network.HTTP.Simple (getResponseBody, httpLBS, parseRequest) -import System.Directory (getCurrentDirectory) import qualified Text.HTML.TagSoup as TS import Text.HTML.TagSoup (Tag) import Text.HTML.TagSoup.Match (anyAttrValue, tagOpen, tagOpenAttrLit, tagOpenAttrNameLit) import Text.Parsec (count, many, parse) import qualified Text.Parsec.Char as P import Text.Parsec.Text (Parser) -import Text.ParserCombinators.Parsec (parseFromFile) -import Util.Helpers import WebParsing.ParsecCombinators (text) import WebParsing.PostParser (addPostToDatabase) import WebParsing.ReqParser (parseReqs) @@ -33,34 +29,6 @@ parseCalendar = do parseArtSci parseBuildings --- The file name is building.csv and it is in the courseography/db folder -buildingsCSV :: IO Prelude.FilePath -buildingsCSV = do - curDir <- getCurrentDirectory - return $ Path.encodeString $ Path.append (Path.decodeString curDir) $ Path.append (Path.decodeString "db") (Path.decodeString "building.csv") - -parseBuildings :: IO () -parseBuildings = do - buildingInfo <- getBuildingsFromCSV =<< buildingsCSV - runDb $ do - liftIO $ putStrLn "Inserting buildings" - deleteWhere ([] :: [Filter Building]) :: SqlPersistM () - insertMany_ buildingInfo :: SqlPersistM () - --- | Extract building names, codes, addresses, postal codes, latitude and longitude from csv file -getBuildingsFromCSV :: String -> IO [Building] -getBuildingsFromCSV buildingCSVFile = do - buildingCSVData <- parseFromFile csvFile buildingCSVFile - case buildingCSVData of - Left _ -> error "csv parse error" - Right buildingData -> do - return $ map (\b -> Building (T.pack $ safeHead "" b) - (T.pack (b !! 1)) - (T.pack (b !! 2)) - (T.pack (b !! 3)) - (read (b !! 4) :: Double) - (read (b !! 5) :: Double)) $ drop 1 buildingData - -- | Parses the entire Arts & Science Course Calendar and inserts courses -- into the database. parseArtSci :: IO () diff --git a/app/WebParsing/UtsgJsonParser.hs b/app/WebParsing/UtsgJsonParser.hs index 860f13876..c1b3899d3 100644 --- a/app/WebParsing/UtsgJsonParser.hs +++ b/app/WebParsing/UtsgJsonParser.hs @@ -10,7 +10,8 @@ import Data.Default.Class (def) import qualified Data.Text as T import Database.Persist.Sqlite (SqlPersistM, Update, deleteWhere, entityKey, insert, insertMany_, selectFirst, upsert, (=.), (==.)) -import Database.Tables (EntityField (..), MeetTime (..), Meeting (..), buildTimes) +import Database.Tables (EntityField (..), MeetTime (..), Meeting (..)) +import Models.Time (buildTimes) import Network.Connection (TLSSettings (TLSSettingsSimple)) import Network.HTTP.Conduit (RequestBody (RequestBodyLBS), httpLbs, method, mkManagerSettings, newManager, parseRequest, requestBody, requestHeaders, responseBody) diff --git a/backend-test/Controllers/CourseControllerTests.hs b/backend-test/Controllers/CourseControllerTests.hs index 7237dad2b..8e904165f 100644 --- a/backend-test/Controllers/CourseControllerTests.hs +++ b/backend-test/Controllers/CourseControllerTests.hs @@ -18,9 +18,9 @@ import qualified Data.Map as Map import Data.Maybe (fromMaybe, mapMaybe) import qualified Data.Text as T import Database.Persist.Sqlite (SqlPersistM, insert, insertMany_, insert_) -import Database.Tables (Building (..), Courses (..), MeetTime (..), Meeting (..), Time' (..), - buildTimes) +import Database.Tables (Building (..), Courses (..), MeetTime (..), Meeting (..), Time' (..)) import Happstack.Server (rsBody, rsCode) +import Models.Time (buildTimes) import Test.Tasty (TestTree) import Test.Tasty.HUnit (assertEqual, testCase) import TestHelpers (clearDatabase, mockGetRequest, runServerPart, runServerPartWith, withDatabase) diff --git a/backend-test/Database/BuildingTests.hs b/backend-test/Database/BuildingTests.hs new file mode 100644 index 000000000..560bfe631 --- /dev/null +++ b/backend-test/Database/BuildingTests.hs @@ -0,0 +1,60 @@ +{-| +Description: Building module tests. + +Module that contains the tests for the functions in the Building module. + +-} + +module Database.BuildingTests +( test_buildings +) where + +import Config (runDb) +import Database.Persist.Sqlite (Filter, selectList) +import Database.Tables (Building) +import Models.Building (buildingsCSV, getBuildingsFromCSV, parseBuildings) +import Test.Tasty (TestTree) +import Test.Tasty.HUnit (assertEqual, testCase) +import TestHelpers (clearDatabase, withDatabase) + +-- | Count the number of buildings currently in the database. +countBuildings :: IO Int +countBuildings = do + buildings <- runDb $ selectList ([] :: [Filter Building]) [] + return $ length buildings + +-- | Count the number of building rows in the CSV that parseBuildings reads. +expectedBuildingCount :: IO Int +expectedBuildingCount = do + csvPath <- buildingsCSV + buildings <- getBuildingsFromCSV csvPath + return $ length buildings + +-- | Run test on parseBuildings to check for a non-zero number of buildings +testParseBuildingsInserts :: TestTree +testParseBuildingsInserts = + testCase "parseBuildings inserts buildings from the CSV" $ do + runDb clearDatabase + parseBuildings + count <- countBuildings + expected <- expectedBuildingCount + assertEqual "Expected parseBuildings to insert every building row from the CSV" expected count + +-- | Run test on parseBuildings to check that calling multiple times does not duplicate entries in the database +testParseBuildingsIdempotent :: TestTree +testParseBuildingsIdempotent = + testCase "parseBuildings is called multiple times and does not duplicate entries" $ do + runDb clearDatabase + parseBuildings + countAfterFirst <- countBuildings + parseBuildings + countAfterSecond <- countBuildings + expected <- expectedBuildingCount + assertEqual "Expected parseBuildings to insert every building row from the CSV" expected countAfterFirst + assertEqual "Expected building count to be the same after multiple calls" + countAfterFirst countAfterSecond + +-- | Test suite for Building module +test_buildings :: TestTree +test_buildings = + withDatabase "Building tests" [testParseBuildingsInserts, testParseBuildingsIdempotent] diff --git a/courseography.cabal b/courseography.cabal index 1d3111f62..3afe3530d 100644 --- a/courseography.cabal +++ b/courseography.cabal @@ -43,10 +43,12 @@ library Export.ImageConversion, Export.TimetableImageCreator, MasterTemplate, + Models.Building, Models.Course, Models.Graph, Models.Meeting, Models.Program, + Models.Time, Scripts, Svg.Builder, Svg.Generator, @@ -119,6 +121,7 @@ test-suite Tests Controllers.GenerateControllerTests, Controllers.GraphControllerTests, Controllers.ProgramControllerTests, + Database.BuildingTests, Database.CourseQueriesTests, Database.TablesTests, RequirementTests.ModifierTests, @@ -188,10 +191,12 @@ executable courseography Export.PdfGenerator, Export.TimetableImageCreator, MasterTemplate, + Models.Building, Models.Course, Models.Graph, Models.Meeting, Models.Program, + Models.Time, Response, Response.About, Response.Draw, From 70767e42bb29b36a9fefc80d5767a203e204609d Mon Sep 17 00:00:00 2001 From: Rui Weng <109623243+r-weng@users.noreply.github.com> Date: Wed, 3 Jun 2026 08:06:26 -0400 Subject: [PATCH 09/39] Removed SvgJSON data type (#1720) Replaced SvgJSON with ([Text], [Shape], [Path]) instead. --- CHANGELOG.md | 1 + app/Controllers/Graph.hs | 12 ++++---- app/Database/Tables.hs | 15 ++-------- app/Models/Graph.hs | 28 ++++++++++++++----- app/Svg/Builder.hs | 5 +++- app/Svg/Generator.hs | 6 +++- app/Svg/Parser.hs | 4 ++- .../Controllers/GraphControllerTests.hs | 18 ++++++------ 8 files changed, 51 insertions(+), 38 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 147c98d38..2f3cdd88d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,7 @@ - Refactor graph helper functions from `app/Svg/Database.hs` to `app/Models/Graph.hs` - Refactor functions for performing matrix operations from `app/Svg/Parser.hs` to `app/Util/Matrix.hs` - Updated documentation in `app/Util/Blaze.hs` +- Removed `SvgJSON` data type in favour of `([Text], [Shape], [Path])` ## [0.7.2] - 2025-12-10 diff --git a/app/Controllers/Graph.hs b/app/Controllers/Graph.hs index 51b4b31f5..d40dd754e 100644 --- a/app/Controllers/Graph.hs +++ b/app/Controllers/Graph.hs @@ -1,7 +1,7 @@ module Controllers.Graph (graphResponse, index, getGraphJSON, graphImageResponse, saveGraphJSON) where import Control.Monad.IO.Class (liftIO) -import Data.Aeson (decode, object, (.=)) +import Data.Aeson (object, (.=)) import Data.Maybe (fromMaybe) import Export.ImageConversion (withImageFile) import Happstack.Server (Response, ServerPart, lookBS, lookText', ok, toResponse) @@ -15,9 +15,9 @@ import qualified Text.Blaze.Html5.Attributes as A import Config (runDb) import Database.Persist.Sqlite (Entity, SelectOpt (Asc), SqlPersistM, selectList, (==.)) -import Database.Tables as Tables (EntityField (GraphDynamic, GraphTitle), Graph, SvgJSON, Text) +import Database.Tables as Tables (EntityField(GraphTitle, GraphDynamic), Text, Graph) import Export.GetImages (writeActiveGraphImage) -import Models.Graph (getGraph, insertGraph) +import Models.Graph (getGraph, insertGraph, parseGraphComponentsJSON) import Util.Happstack (createJSONResponse) import Util.Helpers (readImageData) @@ -64,9 +64,9 @@ saveGraphJSON :: ServerPart Response saveGraphJSON = do jsonStr <- lookBS "jsonData" nameStr <- lookText' "nameData" - let jsonObj = decode jsonStr :: Maybe SvgJSON + let jsonObj = parseGraphComponentsJSON jsonStr case jsonObj of Nothing -> return $ toResponse ("Error" :: String) - Just svg -> do - _ <- liftIO $ runDb $ insertGraph nameStr svg + Just components -> do + _ <- liftIO $ runDb $ insertGraph nameStr components return $ toResponse ("Success" :: String) diff --git a/app/Database/Tables.hs b/app/Database/Tables.hs index ef7061472..6249761fc 100644 --- a/app/Database/Tables.hs +++ b/app/Database/Tables.hs @@ -19,8 +19,8 @@ straightforward. module Database.Tables where -import Data.Aeson (FromJSON (parseJSON), ToJSON (toJSON), genericToJSON, withObject, (.!=), (.:), - (.:?)) +import Data.Aeson (FromJSON (parseJSON), ToJSON (toJSON), genericToJSON, withObject, + (.!=), (.:), (.:?)) import Data.Aeson.Types (Options (..), Parser, Value (Object), defaultOptions) import Data.Char (toLower) import qualified Data.Text as T @@ -160,13 +160,6 @@ SchemaVersion -- ** TODO: Remove these extra types and class instances --- | JSON SVG data -data SvgJSON = - SvgJSON { texts :: [Text], - shapes :: [Shape], - paths :: [Path] - } deriving (Show, Generic) - data Time' = Time' { weekDay' :: Double, startHour' :: Double, @@ -210,10 +203,6 @@ instance ToJSON Time instance ToJSON MeetTime' instance ToJSON Building --- instance FromJSON required so that tables can be parsed into JSON, --- not necessary otherwise. -instance FromJSON SvgJSON - instance ToJSON Meeting where toJSON = genericToJSON defaultOptions { fieldLabelModifier = diff --git a/app/Models/Graph.hs b/app/Models/Graph.hs index 29e4dcf3d..0574d6f6c 100644 --- a/app/Models/Graph.hs +++ b/app/Models/Graph.hs @@ -1,14 +1,17 @@ module Models.Graph - (getGraph, insertGraph, insertElements, deleteExistingGraph) where + (getGraph, insertGraph, insertElements, deleteExistingGraph, parseGraphComponentsJSON) where import Config (runDb) -import Data.Aeson (Value, object, toJSON) +import Data.Aeson (Value, decode, object, toJSON, (.:)) +import Data.Aeson.Types (parseMaybe) import qualified Data.Text as T (Text) +import qualified Data.ByteString.Lazy as L import Database.DataType (ShapeType (BoolNode, Hybrid, Node)) import Database.Persist.Sqlite (Entity, PersistEntity, PersistValue (PersistInt64), SqlPersistM, deleteWhere, entityKey, entityVal, insert, insert_, insertMany_, keyToValues, selectFirst, selectList, (<-.), (==.)) -import Database.Tables hiding (paths, shapes, texts) +import Database.Tables (EntityField(GraphId, ShapeType_, GraphTitle, TextGraph, ShapeGraph, PathGraph), + Key, Path(pathGraph), Shape(shapeGraph), Text(textGraph), Graph(graphWidth, graphHeight, Graph)) import Svg.Builder (buildEllipses, buildPath, buildRect) import Util.Helpers @@ -55,10 +58,10 @@ getGraph graphName = runDb $ do -- | Insert a new graph into the database, given its SVG JSON. -- | Return Nothing. -insertGraph :: T.Text -- ^ The title of the graph being inserted. - -> SvgJSON -- ^ The SVG JSON data of the inserted graph (texts, shapes, paths). - -> SqlPersistM () -- ^ Return Nothing. -insertGraph nameStr_ (SvgJSON texts shapes paths) = do +insertGraph :: T.Text -- ^ The title of the graph being inserted. + -> ([Text], [Shape], [Path]) -- ^ The parsed JSON data of the inserted graph. + -> SqlPersistM () -- ^ Return Nothing. +insertGraph nameStr_ (texts, shapes, paths) = do gId <- insert $ Graph nameStr_ 256 256 False insertMany_ $ map (\text -> text {textGraph = gId}) texts insertMany_ $ map (\shape -> shape {shapeGraph = gId}) shapes @@ -88,3 +91,14 @@ deleteGraph gId = do deleteWhere [ShapeGraph ==. gId] deleteWhere [PathGraph ==. gId] deleteWhere [GraphId ==. gId] + +-- | Parse the JSON representation of a graph into its texts, shapes, and paths components. +parseGraphComponentsJSON :: L.ByteString -> Maybe ([Text], [Shape], [Path]) +parseGraphComponentsJSON jsonStr = do + obj <- decode jsonStr + parseMaybe (\o -> do + texts <- o .: "texts" + shapes <- o .: "shapes" + paths <- o .: "paths" + return (texts, shapes, paths) + ) obj diff --git a/app/Svg/Builder.hs b/app/Svg/Builder.hs index cd5a51f2f..6d8f8b6bf 100644 --- a/app/Svg/Builder.hs +++ b/app/Svg/Builder.hs @@ -21,7 +21,10 @@ import Data.Char (toLower) import Data.List (find) import qualified Data.Text as T import Database.DataType -import Database.Tables hiding (shapes, texts) +import Database.Tables (Matrix, Point, + Path(pathTarget, pathIsRegion, pathPoints, pathTransform, pathId_, pathSource), + Shape(shapeText, shapeWidth, shapeHeight, shapePos, shapeTransform, shapeType_, shapeId_), + Text(textPos, textText, textTransform)) import Util.Matrix (matrixPointMultiply) import TextShow (showt) import Util.Helpers diff --git a/app/Svg/Generator.hs b/app/Svg/Generator.hs index ffd69c94f..509eb81ce 100644 --- a/app/Svg/Generator.hs +++ b/app/Svg/Generator.hs @@ -21,7 +21,11 @@ import Data.Maybe (fromMaybe) import qualified Data.Text as T import Database.DataType import Database.Persist.Sqlite -import Database.Tables hiding (paths, texts) +import Database.Tables (EntityField(ShapeGraph, GraphTitle, TextGraph, PathGraph, ShapeType_), + Path(pathFill, pathIsRegion, pathSource, pathTarget, pathId_, pathPoints, pathTransform), + Shape(shapeText, shapeFill, shapeType_, shapeId_, shapeTransform, shapeWidth, shapeHeight, shapePos), + Text(textText, textPos, textAlign, textFill, textTransform), + Graph(graphHeight, graphWidth)) import Svg.Builder import System.IO (Handle, hPutStrLn) import Text.Blaze (toMarkup) diff --git a/app/Svg/Parser.hs b/app/Svg/Parser.hs index a9be16f3b..85b60c11e 100644 --- a/app/Svg/Parser.hs +++ b/app/Svg/Parser.hs @@ -25,7 +25,9 @@ import qualified Data.Text as T import Data.Text.IO as T (readFile) import Database.DataType import Database.Persist.Sqlite -import Database.Tables hiding (graphHeight, graphWidth, paths, shapes, texts) +import Database.Tables (Matrix, Point, + Path(pathFill, Path), Shape(shapeType_, shapeWidth, shapePos, Shape, shapeFill), + Text(Text), Graph(Graph), GraphId) import Models.Graph (deleteExistingGraph, insertElements) import qualified Text.HTML.TagSoup as TS hiding (fromAttrib) import Text.HTML.TagSoup (Tag) diff --git a/backend-test/Controllers/GraphControllerTests.hs b/backend-test/Controllers/GraphControllerTests.hs index 9910dfb59..46ef7fda1 100644 --- a/backend-test/Controllers/GraphControllerTests.hs +++ b/backend-test/Controllers/GraphControllerTests.hs @@ -18,9 +18,9 @@ import qualified Data.Aeson.KeyMap as KeyMap import qualified Data.ByteString.Lazy.Char8 as BL import qualified Data.Text as T import Database.Persist.Sqlite (SqlPersistM, insert_, toSqlKey) -import Database.Tables (Graph (..), Path (..), Shape (..), Text (..), SvgJSON (..)) +import Database.Tables (Graph(Graph), Path(..), Shape(..), Text(..)) import Happstack.Server (rsBody) -import Models.Graph (getGraph, insertGraph) +import Models.Graph (getGraph, insertGraph, parseGraphComponentsJSON) import Test.Tasty (TestTree) import Test.Tasty.HUnit (assertEqual, assertFailure, testCase) import TestHelpers (clearDatabase, mockPutRequest, runServerPart, runServerPartWith, withDatabase, mockGetRequest) @@ -187,16 +187,16 @@ runGetGraphJSONTest (label, (texts', shapes', paths')) = let graphName = "Test Graph Name" runDb $ do clearDatabase - insertGraph graphName (SvgJSON texts' shapes' paths') + insertGraph graphName (texts', shapes', paths') response <- runServerPartWith Controllers.Graph.getGraphJSON $ mockGetRequest "/get-json-data" [("graphName", T.unpack graphName)] "" let body = rsBody response - let jsonObj = decode body :: Maybe SvgJSON + let jsonObj = parseGraphComponentsJSON body case jsonObj of - Nothing -> assertFailure ("Maybe SvgJSON returned as Nothing for " ++ label) - Just svg -> do - assertEqual ("Texts differ for " ++ label) texts' (map (\text -> text {textGraph = toSqlKey 1}) (texts svg)) - assertEqual ("Shapes differ for " ++ label) shapes' (map (\shape -> shape {shapeGraph = toSqlKey 1}) (shapes svg)) - assertEqual ("Paths differ for " ++ label) paths' (map (\path -> path {pathGraph = toSqlKey 1}) (paths svg)) + Nothing -> assertFailure ("Maybe ([Text], [Shape], [Path]) returned as Nothing for " ++ label) + Just (parsedTexts, parsedShapes, parsedPaths) -> do + assertEqual ("Texts differ for " ++ label) texts' (map (\text -> text {textGraph = toSqlKey 1}) parsedTexts) + assertEqual ("Shapes differ for " ++ label) shapes' (map (\shape -> shape {shapeGraph = toSqlKey 1}) parsedShapes) + assertEqual ("Paths differ for " ++ label) paths' (map (\path -> path {pathGraph = toSqlKey 1}) parsedPaths) -- | Run all getGraphJSON tests runGetGraphJSONTests :: [TestTree] From 150bafe9523a5a2e6a847272290a41a2bbf43cde Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Jun 2026 19:59:16 -0400 Subject: [PATCH 10/39] build(deps-dev): bump the jest group with 2 updates (#1724) Bumps the jest group with 2 updates: [jest](https://github.com/jestjs/jest/tree/HEAD/packages/jest) and [jest-environment-jsdom](https://github.com/jestjs/jest/tree/HEAD/packages/jest-environment-jsdom). Updates `jest` from 30.3.0 to 30.4.2 - [Release notes](https://github.com/jestjs/jest/releases) - [Changelog](https://github.com/jestjs/jest/blob/main/CHANGELOG.md) - [Commits](https://github.com/jestjs/jest/commits/v30.4.2/packages/jest) Updates `jest-environment-jsdom` from 30.3.0 to 30.4.1 - [Release notes](https://github.com/jestjs/jest/releases) - [Changelog](https://github.com/jestjs/jest/blob/main/CHANGELOG.md) - [Commits](https://github.com/jestjs/jest/commits/v30.4.1/packages/jest-environment-jsdom) --- updated-dependencies: - dependency-name: jest dependency-version: 30.4.2 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: jest - dependency-name: jest-environment-jsdom dependency-version: 30.4.1 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: jest ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 4 +- yarn.lock | 763 ++++++++++++++++++++++++++------------------------- 2 files changed, 392 insertions(+), 375 deletions(-) diff --git a/package.json b/package.json index 54d48b04d..d64a254fe 100644 --- a/package.json +++ b/package.json @@ -70,8 +70,8 @@ "globals": "^15.14.0", "html-loader": "^5.1.0", "husky": "^9.1.7", - "jest": "^30.3.0", - "jest-environment-jsdom": "^30.3.0", + "jest": "^30.4.2", + "jest-environment-jsdom": "^30.4.1", "lint-staged": "^16.2.7", "markdown-loader": "^8.0.0", "mini-css-extract-plugin": "^2.9.2", diff --git a/yarn.lock b/yarn.lock index 5fb9bd050..faf4bf67c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2249,130 +2249,131 @@ __metadata: languageName: node linkType: hard -"@jest/console@npm:30.3.0": - version: 30.3.0 - resolution: "@jest/console@npm:30.3.0" +"@jest/console@npm:30.4.1": + version: 30.4.1 + resolution: "@jest/console@npm:30.4.1" dependencies: - "@jest/types": 30.3.0 + "@jest/types": 30.4.1 "@types/node": "*" chalk: ^4.1.2 - jest-message-util: 30.3.0 - jest-util: 30.3.0 + jest-message-util: 30.4.1 + jest-util: 30.4.1 slash: ^3.0.0 - checksum: d74bacf7229d5ac08918e8e8d43a7cfda70edae3925eb4e4ad57d890f689c1ad6f2baa1afb3cb816d94919f5b41a0745219de61ac60b2fc968f041ef4dad93c7 + checksum: 21d179fb96a17a622b1b15c3d2ced4c83ae9b3912012505e4720701383f8e0e0d32c41b4c6adeeaaadd193b821d5759425cd1a774ba8ab4924213f218bd50125 languageName: node linkType: hard -"@jest/core@npm:30.3.0": - version: 30.3.0 - resolution: "@jest/core@npm:30.3.0" +"@jest/core@npm:30.4.2": + version: 30.4.2 + resolution: "@jest/core@npm:30.4.2" dependencies: - "@jest/console": 30.3.0 - "@jest/pattern": 30.0.1 - "@jest/reporters": 30.3.0 - "@jest/test-result": 30.3.0 - "@jest/transform": 30.3.0 - "@jest/types": 30.3.0 + "@jest/console": 30.4.1 + "@jest/pattern": 30.4.0 + "@jest/reporters": 30.4.1 + "@jest/test-result": 30.4.1 + "@jest/transform": 30.4.1 + "@jest/types": 30.4.1 "@types/node": "*" ansi-escapes: ^4.3.2 chalk: ^4.1.2 ci-info: ^4.2.0 exit-x: ^0.2.2 + fast-json-stable-stringify: ^2.1.0 graceful-fs: ^4.2.11 - jest-changed-files: 30.3.0 - jest-config: 30.3.0 - jest-haste-map: 30.3.0 - jest-message-util: 30.3.0 - jest-regex-util: 30.0.1 - jest-resolve: 30.3.0 - jest-resolve-dependencies: 30.3.0 - jest-runner: 30.3.0 - jest-runtime: 30.3.0 - jest-snapshot: 30.3.0 - jest-util: 30.3.0 - jest-validate: 30.3.0 - jest-watcher: 30.3.0 - pretty-format: 30.3.0 + jest-changed-files: 30.4.1 + jest-config: 30.4.2 + jest-haste-map: 30.4.1 + jest-message-util: 30.4.1 + jest-regex-util: 30.4.0 + jest-resolve: 30.4.1 + jest-resolve-dependencies: 30.4.2 + jest-runner: 30.4.2 + jest-runtime: 30.4.2 + jest-snapshot: 30.4.1 + jest-util: 30.4.1 + jest-validate: 30.4.1 + jest-watcher: 30.4.1 + pretty-format: 30.4.1 slash: ^3.0.0 peerDependencies: node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 peerDependenciesMeta: node-notifier: optional: true - checksum: 15a8823e736e9ce7bee58f46e5306cdcc8bf2d29d0697ba5c256b6fe94f5aa79edb21a13acb01e460787a1d6c8447c771750e27e46fc58c91b35ca15070b7a7c + checksum: c405da432cbabbde153f90af8a96f52eec62764eb4f973e1b23c2f6dc173e2dac4c264119f513fb3b39cbaaaccb71dab2b0e0ca2cb3529d687ccdfe9eee2e383 languageName: node linkType: hard -"@jest/diff-sequences@npm:30.3.0": - version: 30.3.0 - resolution: "@jest/diff-sequences@npm:30.3.0" - checksum: 715325e544f54cf5336b54fbfecd3e7e0e779b96c1f28a2ab42fdd4388f5f3751558a474d173b0c43bc5fb513fbb0464dbf1503cc69dab248515c6ed42feecb3 +"@jest/diff-sequences@npm:30.4.0": + version: 30.4.0 + resolution: "@jest/diff-sequences@npm:30.4.0" + checksum: a391acfbb6b349558c2c84643b4790be70e466d09bdca2eee8e4cb533cb0b5652930f591614fe05d39681e212cf984c790a770e282602c1645c561d85e8b64ee languageName: node linkType: hard -"@jest/environment-jsdom-abstract@npm:30.3.0": - version: 30.3.0 - resolution: "@jest/environment-jsdom-abstract@npm:30.3.0" +"@jest/environment-jsdom-abstract@npm:30.4.1": + version: 30.4.1 + resolution: "@jest/environment-jsdom-abstract@npm:30.4.1" dependencies: - "@jest/environment": 30.3.0 - "@jest/fake-timers": 30.3.0 - "@jest/types": 30.3.0 + "@jest/environment": 30.4.1 + "@jest/fake-timers": 30.4.1 + "@jest/types": 30.4.1 "@types/jsdom": ^21.1.7 "@types/node": "*" - jest-mock: 30.3.0 - jest-util: 30.3.0 + jest-mock: 30.4.1 + jest-util: 30.4.1 peerDependencies: canvas: ^3.0.0 jsdom: "*" peerDependenciesMeta: canvas: optional: true - checksum: 26c310e0dc67cd5c0b265e164a1d3d114ee057b8de196fe91473bd0157942f99a2e29695fdccfd6d24da69eddb81afc05239bef8b9c2a9434f23876143175d17 + checksum: 75d572199b17a50f7ce268e61cdab143bb19d0b39057dc765d4b016a331895babb8d7884795a685a84461bca24b791f73790241e96556366aaf6bef949778fe7 languageName: node linkType: hard -"@jest/environment@npm:30.3.0": - version: 30.3.0 - resolution: "@jest/environment@npm:30.3.0" +"@jest/environment@npm:30.4.1": + version: 30.4.1 + resolution: "@jest/environment@npm:30.4.1" dependencies: - "@jest/fake-timers": 30.3.0 - "@jest/types": 30.3.0 + "@jest/fake-timers": 30.4.1 + "@jest/types": 30.4.1 "@types/node": "*" - jest-mock: 30.3.0 - checksum: c58121d7161e5906ae46407fe1f6e2289675b1cb9dcb6079e9ce2ea2042ee029c0216860367a31660fe54de3387322b4627bf4704d10cefbe718ab72a522889d + jest-mock: 30.4.1 + checksum: 4b3b25a0727f97d3b1e3023d376861ee60fc3d31a8f41270180c1a37229f1d87f974467236e4b9ded146147408904450060fed470b2f34d2d2f86c502b42a7c9 languageName: node linkType: hard -"@jest/expect-utils@npm:30.3.0": - version: 30.3.0 - resolution: "@jest/expect-utils@npm:30.3.0" +"@jest/expect-utils@npm:30.4.1": + version: 30.4.1 + resolution: "@jest/expect-utils@npm:30.4.1" dependencies: "@jest/get-type": 30.1.0 - checksum: 963ebcf5dd3c3ef1b8f932d04f5f594357fcc277089c56fd0bfcabfbdd9b0150c0bf6e13e3a8c5084c8799f019e4e8487b13cebfe31be7992016fe0ca7e9fcf7 + checksum: c458d8b1bb26783d21ba8a911cd476deab02af29046fd67b9eadf0be6bec2b90285bff1b443bb1c69f72b8f65ef9e06d96d17a1fd65bb394747d544339451cec languageName: node linkType: hard -"@jest/expect@npm:30.3.0": - version: 30.3.0 - resolution: "@jest/expect@npm:30.3.0" +"@jest/expect@npm:30.4.1": + version: 30.4.1 + resolution: "@jest/expect@npm:30.4.1" dependencies: - expect: 30.3.0 - jest-snapshot: 30.3.0 - checksum: 3dd5d266f85348aec70ee06aa0ea14fd75176f09163761375910be3fa3d7ae05815a2e6daf7ff8541afcd4c61800892b48b74ddfe0ecbe5821812b2dad5e1809 + expect: 30.4.1 + jest-snapshot: 30.4.1 + checksum: 0de7505ec903bd821ea34056212701220ac5fce67c98ce178c6cc683a3c5ff46d633f250e62870b7b339cb5981467e008bb34633374f8dc1eee7c078d3be8b60 languageName: node linkType: hard -"@jest/fake-timers@npm:30.3.0": - version: 30.3.0 - resolution: "@jest/fake-timers@npm:30.3.0" +"@jest/fake-timers@npm:30.4.1": + version: 30.4.1 + resolution: "@jest/fake-timers@npm:30.4.1" dependencies: - "@jest/types": 30.3.0 - "@sinonjs/fake-timers": ^15.0.0 + "@jest/types": 30.4.1 + "@sinonjs/fake-timers": ^15.4.0 "@types/node": "*" - jest-message-util: 30.3.0 - jest-mock: 30.3.0 - jest-util: 30.3.0 - checksum: 6854e881a50f70f518935d1f83ace2e63bc55fc71f19145442da7cf30a26edec348b5f0ac3993d9c48a9dd0dbfd7be0c9a13d82fe481fd48bc055fdd5a6abfa3 + jest-message-util: 30.4.1 + jest-mock: 30.4.1 + jest-util: 30.4.1 + checksum: 7551cade630924ba1ba4aad84553ac2c4238c18cd134433f16804df81018785c174a7ec1bafbeb566b1cca711fd8c0b5779d7ec6bf2b6eaa1eebb4b4e81a9bcb languageName: node linkType: hard @@ -2383,37 +2384,37 @@ __metadata: languageName: node linkType: hard -"@jest/globals@npm:30.3.0": - version: 30.3.0 - resolution: "@jest/globals@npm:30.3.0" +"@jest/globals@npm:30.4.1": + version: 30.4.1 + resolution: "@jest/globals@npm:30.4.1" dependencies: - "@jest/environment": 30.3.0 - "@jest/expect": 30.3.0 - "@jest/types": 30.3.0 - jest-mock: 30.3.0 - checksum: 485bdc0f35faf3e76cb451b75e16892d87f7ab5757e290b1a9e849a3af0ef81c47abddb188fbc0442a4689514cf0551e34d13970c9cf03610a269c39f800ff46 + "@jest/environment": 30.4.1 + "@jest/expect": 30.4.1 + "@jest/types": 30.4.1 + jest-mock: 30.4.1 + checksum: 5fe04b9c3b97f0061e4464201ee0dd674dd958843eb80542791d1c576c51f12aaa3f3b369e136d5fd3f8c716f9c9bbfbb76491a3cbc3c4efb3cc71063f909132 languageName: node linkType: hard -"@jest/pattern@npm:30.0.1": - version: 30.0.1 - resolution: "@jest/pattern@npm:30.0.1" +"@jest/pattern@npm:30.4.0": + version: 30.4.0 + resolution: "@jest/pattern@npm:30.4.0" dependencies: "@types/node": "*" - jest-regex-util: 30.0.1 - checksum: 1a1857df19be87e714786c3ab36862702bf8ed1e2665044b2ce5ffa787b5ab74c876f1756e83d3b09737dd98c1e980e259059b65b9b0f49b03716634463a8f9e + jest-regex-util: 30.4.0 + checksum: d0877dc7034cb59e9eafb8fedd6b977a1cd91191d7ac2574c0c0d046074ef7c895f0952af1586898469dcceb0153230a32b67a45bc4dd1ee2ae66df371b95363 languageName: node linkType: hard -"@jest/reporters@npm:30.3.0": - version: 30.3.0 - resolution: "@jest/reporters@npm:30.3.0" +"@jest/reporters@npm:30.4.1": + version: 30.4.1 + resolution: "@jest/reporters@npm:30.4.1" dependencies: "@bcoe/v8-coverage": ^0.2.3 - "@jest/console": 30.3.0 - "@jest/test-result": 30.3.0 - "@jest/transform": 30.3.0 - "@jest/types": 30.3.0 + "@jest/console": 30.4.1 + "@jest/test-result": 30.4.1 + "@jest/transform": 30.4.1 + "@jest/types": 30.4.1 "@jridgewell/trace-mapping": ^0.3.25 "@types/node": "*" chalk: ^4.1.2 @@ -2426,9 +2427,9 @@ __metadata: istanbul-lib-report: ^3.0.0 istanbul-lib-source-maps: ^5.0.0 istanbul-reports: ^3.1.3 - jest-message-util: 30.3.0 - jest-util: 30.3.0 - jest-worker: 30.3.0 + jest-message-util: 30.4.1 + jest-util: 30.4.1 + jest-worker: 30.4.1 slash: ^3.0.0 string-length: ^4.0.2 v8-to-istanbul: ^9.0.1 @@ -2437,16 +2438,16 @@ __metadata: peerDependenciesMeta: node-notifier: optional: true - checksum: ffafe5f4d6dce6eb73576890705b77e4792c7d003d897dfbda2569d78d17b5585917ce875200de2bcba1e2c34c83af28c68cb665b7e8f8359fb9499a26f5f5a0 + checksum: 55b88b358103b1ebc46e8342e520165e983d539c5fe427534b2817f341985012e2ee09002674270ef69d87292325a2ba1182aa1c89446d01bd1834879307598a languageName: node linkType: hard -"@jest/schemas@npm:30.0.5": - version: 30.0.5 - resolution: "@jest/schemas@npm:30.0.5" +"@jest/schemas@npm:30.4.1": + version: 30.4.1 + resolution: "@jest/schemas@npm:30.4.1" dependencies: "@sinclair/typebox": ^0.34.0 - checksum: 7a4fc4166f688947c22d81e61aaf2cb22f178dbf6ee806b0931b75136899d426a72a8330762f27f0cf6f79da0d2a56f49a22fe09f5f80df95a683ed237a0f3b0 + checksum: 25d0db478805adff276e02f9e1b5a90d5962e51020503eede22edee432de3958654edddca0e66988c515fa7bc06461f5220826de9f76fcc89c5824e88d624842 languageName: node linkType: hard @@ -2459,15 +2460,15 @@ __metadata: languageName: node linkType: hard -"@jest/snapshot-utils@npm:30.3.0": - version: 30.3.0 - resolution: "@jest/snapshot-utils@npm:30.3.0" +"@jest/snapshot-utils@npm:30.4.1": + version: 30.4.1 + resolution: "@jest/snapshot-utils@npm:30.4.1" dependencies: - "@jest/types": 30.3.0 + "@jest/types": 30.4.1 chalk: ^4.1.2 graceful-fs: ^4.2.11 natural-compare: ^1.4.0 - checksum: 5cbc5622bf83cc876ad237fa780bc9b64196a5536469a37d7042c25ec70c299cb610103445af8bdadc2a507e11142ca7f47a74ca8f4c372c2dc076091b3725a1 + checksum: 0e561d6a8af6a35bc6a37e649229f049efa5a62e4325aafd26803a230f6f5ffcdc87f376b8c400bdf480fef32681c7379cb3db30707c98530018d6f8d7f201a1 languageName: node linkType: hard @@ -2482,49 +2483,49 @@ __metadata: languageName: node linkType: hard -"@jest/test-result@npm:30.3.0": - version: 30.3.0 - resolution: "@jest/test-result@npm:30.3.0" +"@jest/test-result@npm:30.4.1": + version: 30.4.1 + resolution: "@jest/test-result@npm:30.4.1" dependencies: - "@jest/console": 30.3.0 - "@jest/types": 30.3.0 + "@jest/console": 30.4.1 + "@jest/types": 30.4.1 "@types/istanbul-lib-coverage": ^2.0.6 collect-v8-coverage: ^1.0.2 - checksum: 63dadb4c94037260be3fa23ec82e9c9c953e6252e5ee5535b443209e7148d1d8eda8a9b59fff8bae8df24274b057c5a990715cb49c010852cd4b3e3bcdf2bd69 + checksum: 2db40181451f21b7dcc8295fb132a1172dd7487a1d63bf105263225bec2a0d973f764b0a424f9b5a2db2ceb9d0f507c27261834bb1867d5e3eecd9e6c824243c languageName: node linkType: hard -"@jest/test-sequencer@npm:30.3.0": - version: 30.3.0 - resolution: "@jest/test-sequencer@npm:30.3.0" +"@jest/test-sequencer@npm:30.4.1": + version: 30.4.1 + resolution: "@jest/test-sequencer@npm:30.4.1" dependencies: - "@jest/test-result": 30.3.0 + "@jest/test-result": 30.4.1 graceful-fs: ^4.2.11 - jest-haste-map: 30.3.0 + jest-haste-map: 30.4.1 slash: ^3.0.0 - checksum: 46d1ca2b8e5c26cbc9d37b7b6a762000aa7d57662a230e3db097f2b27237aba020d40ea5024863652e16493d404d0c2b236683159a63ab0fda47b578654cac9c + checksum: 0374978dfce5b59ae83549f01cf0d92c7587e356f5d9f10c92e14b7ed857bb28596550ce5d4cf939cd985ffb7d21419855f36d04577c1eb4ed82e31bde2f9bc4 languageName: node linkType: hard -"@jest/transform@npm:30.3.0": - version: 30.3.0 - resolution: "@jest/transform@npm:30.3.0" +"@jest/transform@npm:30.4.1": + version: 30.4.1 + resolution: "@jest/transform@npm:30.4.1" dependencies: "@babel/core": ^7.27.4 - "@jest/types": 30.3.0 + "@jest/types": 30.4.1 "@jridgewell/trace-mapping": ^0.3.25 babel-plugin-istanbul: ^7.0.1 chalk: ^4.1.2 convert-source-map: ^2.0.0 fast-json-stable-stringify: ^2.1.0 graceful-fs: ^4.2.11 - jest-haste-map: 30.3.0 - jest-regex-util: 30.0.1 - jest-util: 30.3.0 + jest-haste-map: 30.4.1 + jest-regex-util: 30.4.0 + jest-util: 30.4.1 pirates: ^4.0.7 slash: ^3.0.0 write-file-atomic: ^5.0.1 - checksum: 0327d28d4ee3903ebd415e1974c9aae6c7e7a7d1770aa07c551d34666851283125f488ec1366fa8814402bdfbd83be9b45ad551839bb407c468fa6bdb44e7d0c + checksum: 5b35a721774cdf7dd8a257b3d47b02ecc1705c7256a569d0105511992d8143ab89f6b247fbe07fdadff1499b4e1f3ecc9f128ed778f72203ba358f29a885ed5d languageName: node linkType: hard @@ -2551,18 +2552,18 @@ __metadata: languageName: node linkType: hard -"@jest/types@npm:30.3.0": - version: 30.3.0 - resolution: "@jest/types@npm:30.3.0" +"@jest/types@npm:30.4.1": + version: 30.4.1 + resolution: "@jest/types@npm:30.4.1" dependencies: - "@jest/pattern": 30.0.1 - "@jest/schemas": 30.0.5 + "@jest/pattern": 30.4.0 + "@jest/schemas": 30.4.1 "@types/istanbul-lib-coverage": ^2.0.6 "@types/istanbul-reports": ^3.0.4 "@types/node": "*" "@types/yargs": ^17.0.33 chalk: ^4.1.2 - checksum: ee77d038ff965b136d5509acdd477e882938961094ee4a3556555d72a1e454da99679b73c4ddd19653b1aaf3b9cd97db04114d090b31d9e6939690223eac00af + checksum: 746fbb96609c8cc2638a59b23e1d0e590527a301909a22728bc6dab35593ec967f45664fbd00b51fb48a53934d9be2f5df625db7a741c5caae734746d7b41046 languageName: node linkType: hard @@ -3299,12 +3300,12 @@ __metadata: languageName: node linkType: hard -"@sinonjs/fake-timers@npm:^15.0.0": - version: 15.3.0 - resolution: "@sinonjs/fake-timers@npm:15.3.0" +"@sinonjs/fake-timers@npm:^15.4.0": + version: 15.4.0 + resolution: "@sinonjs/fake-timers@npm:15.4.0" dependencies: "@sinonjs/commons": ^3.0.1 - checksum: c7af975708e651be940863efded9796658fb1a9bf41322b957e8cc77cc4592b3da53c17685b05a1d30929cf65e21654fede5a37b7c09d453cf7be2f7040f51a4 + checksum: 89714334b84c0dd5ef84cc01ec99d7d16529297fc32a68c28e4793b89bac0de7b373310b736ed4a57697de92eca4e7cc62c2ec4fae1e651787345e2564b707f4 languageName: node linkType: hard @@ -4584,20 +4585,20 @@ __metadata: languageName: node linkType: hard -"babel-jest@npm:30.3.0": - version: 30.3.0 - resolution: "babel-jest@npm:30.3.0" +"babel-jest@npm:30.4.1": + version: 30.4.1 + resolution: "babel-jest@npm:30.4.1" dependencies: - "@jest/transform": 30.3.0 + "@jest/transform": 30.4.1 "@types/babel__core": ^7.20.5 babel-plugin-istanbul: ^7.0.1 - babel-preset-jest: 30.3.0 + babel-preset-jest: 30.4.0 chalk: ^4.1.2 graceful-fs: ^4.2.11 slash: ^3.0.0 peerDependencies: "@babel/core": ^7.11.0 || ^8.0.0-0 - checksum: edcee70837cc3c88e2992e6bbaaf7bba2c0d56b215cdca0a0cee214d8a47360fbcdc45117ac50cba6cb077465d045edc1285812e6df45caad9a4786a12696a1d + checksum: 9704c2fa202d5db5347492ae423552b8224c99102258a5446dcb0f032dea37de9fbadf37f912247db145840731f38567382c5298aef4f59afb671407af37dc00 languageName: node linkType: hard @@ -4656,12 +4657,12 @@ __metadata: languageName: node linkType: hard -"babel-plugin-jest-hoist@npm:30.3.0": - version: 30.3.0 - resolution: "babel-plugin-jest-hoist@npm:30.3.0" +"babel-plugin-jest-hoist@npm:30.4.0": + version: 30.4.0 + resolution: "babel-plugin-jest-hoist@npm:30.4.0" dependencies: "@types/babel__core": ^7.20.5 - checksum: 5d169656b7ef665a1d7669168ffe6f560aa190c98b2a13793a8d9c671cb107985bff2e93dc1af621d46fd81cae497f6476dc966a14a1f290318f2afdcaf88ddf + checksum: 5a4541c15405bd238589150bf459495ae4eac52c69707a2fb63270d0ff85cdb0aa33caa79cf153312491ba64b211b3fda53003dfdd9f38fb6a89cc36a3decb2b languageName: node linkType: hard @@ -4749,15 +4750,15 @@ __metadata: languageName: node linkType: hard -"babel-preset-jest@npm:30.3.0": - version: 30.3.0 - resolution: "babel-preset-jest@npm:30.3.0" +"babel-preset-jest@npm:30.4.0": + version: 30.4.0 + resolution: "babel-preset-jest@npm:30.4.0" dependencies: - babel-plugin-jest-hoist: 30.3.0 + babel-plugin-jest-hoist: 30.4.0 babel-preset-current-node-syntax: ^1.2.0 peerDependencies: "@babel/core": ^7.11.0 || ^8.0.0-beta.1 - checksum: fd29c8ff5967c047006bde152cf5ac99ce2e1d573f6f044828cb4d06eab95b65549a38554ea97174bbe508006d2a7cb1370581d87aa73f6b3c2134f2d49aaf85 + checksum: 7fbdcaa1f24b2efbc1b658220df849a375858bd5e208cefcf53b116bca972b28565a0715521cc20bec41adbd20ff73b9dbbdea3634bd71f50062f0ce694a7159 languageName: node linkType: hard @@ -5596,8 +5597,8 @@ __metadata: handlebars: ^4.7.9 html-loader: ^5.1.0 husky: ^9.1.7 - jest: ^30.3.0 - jest-environment-jsdom: ^30.3.0 + jest: ^30.4.2 + jest-environment-jsdom: ^30.4.1 jquery: ^3.7.1 leaflet: ^1.9.3 lint-staged: ^16.2.7 @@ -6728,17 +6729,17 @@ __metadata: languageName: node linkType: hard -"expect@npm:30.3.0": - version: 30.3.0 - resolution: "expect@npm:30.3.0" +"expect@npm:30.4.1": + version: 30.4.1 + resolution: "expect@npm:30.4.1" dependencies: - "@jest/expect-utils": 30.3.0 + "@jest/expect-utils": 30.4.1 "@jest/get-type": 30.1.0 - jest-matcher-utils: 30.3.0 - jest-message-util: 30.3.0 - jest-mock: 30.3.0 - jest-util: 30.3.0 - checksum: 1563465523364c6d01d7b8e7bf61a662f312b611757c755c1e9ed98dfa2ffac10664d5ed4119350cf8a8a64ec38eea5a2606d0c48af41dacb25f5b7e17c59468 + jest-matcher-utils: 30.4.1 + jest-message-util: 30.4.1 + jest-mock: 30.4.1 + jest-util: 30.4.1 + checksum: b128d5cf1e072f504075d5a4ee9487d9310a8382129cc117fd1ea3a473ada5da7463a9c0537e58519be3d9d789900e9863e65280aa712b8762de627a07fe4371 languageName: node linkType: hard @@ -8558,58 +8559,58 @@ __metadata: languageName: node linkType: hard -"jest-changed-files@npm:30.3.0": - version: 30.3.0 - resolution: "jest-changed-files@npm:30.3.0" +"jest-changed-files@npm:30.4.1": + version: 30.4.1 + resolution: "jest-changed-files@npm:30.4.1" dependencies: execa: ^5.1.1 - jest-util: 30.3.0 + jest-util: 30.4.1 p-limit: ^3.1.0 - checksum: d4f03a0e2bd26c6e39d73618a361f0b11c8bcf0c479e3a32a1e9b3ceecafc26514c52d26dd3ee91ede1be72a2ef3d22a3443a0f71b1fec21ef462fb48e6de1e8 + checksum: aa0bd15e1df7c724af9f1af1346906fb65bdab7535580469493f8cced015f81a333e6bcd5cdde6a22a7aa43eece8859c0c83ec0a11f728423bb0cca088f6f8a6 languageName: node linkType: hard -"jest-circus@npm:30.3.0": - version: 30.3.0 - resolution: "jest-circus@npm:30.3.0" +"jest-circus@npm:30.4.2": + version: 30.4.2 + resolution: "jest-circus@npm:30.4.2" dependencies: - "@jest/environment": 30.3.0 - "@jest/expect": 30.3.0 - "@jest/test-result": 30.3.0 - "@jest/types": 30.3.0 + "@jest/environment": 30.4.1 + "@jest/expect": 30.4.1 + "@jest/test-result": 30.4.1 + "@jest/types": 30.4.1 "@types/node": "*" chalk: ^4.1.2 co: ^4.6.0 dedent: ^1.6.0 is-generator-fn: ^2.1.0 - jest-each: 30.3.0 - jest-matcher-utils: 30.3.0 - jest-message-util: 30.3.0 - jest-runtime: 30.3.0 - jest-snapshot: 30.3.0 - jest-util: 30.3.0 + jest-each: 30.4.1 + jest-matcher-utils: 30.4.1 + jest-message-util: 30.4.1 + jest-runtime: 30.4.2 + jest-snapshot: 30.4.1 + jest-util: 30.4.1 p-limit: ^3.1.0 - pretty-format: 30.3.0 + pretty-format: 30.4.1 pure-rand: ^7.0.0 slash: ^3.0.0 stack-utils: ^2.0.6 - checksum: f4bd673e265da8021a737dd6903280809047763e36d6bc91d07aa279601f939e44f98cb8b2154f05a03e9cd4eec67c7f839959a90248da77e7b7f0ed3238672e + checksum: d9de058202b124b72dc9387a5478719c1470419cb1265caf110bd469bf6f6b4544a44f60f261b0857ac6e3c2049d465c84e7707d64854191fb7e3f118dbeab7c languageName: node linkType: hard -"jest-cli@npm:30.3.0": - version: 30.3.0 - resolution: "jest-cli@npm:30.3.0" +"jest-cli@npm:30.4.2": + version: 30.4.2 + resolution: "jest-cli@npm:30.4.2" dependencies: - "@jest/core": 30.3.0 - "@jest/test-result": 30.3.0 - "@jest/types": 30.3.0 + "@jest/core": 30.4.2 + "@jest/test-result": 30.4.1 + "@jest/types": 30.4.1 chalk: ^4.1.2 exit-x: ^0.2.2 import-local: ^3.2.0 - jest-config: 30.3.0 - jest-util: 30.3.0 - jest-validate: 30.3.0 + jest-config: 30.4.2 + jest-util: 30.4.1 + jest-validate: 30.4.1 yargs: ^17.7.2 peerDependencies: node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 @@ -8618,35 +8619,35 @@ __metadata: optional: true bin: jest: ./bin/jest.js - checksum: a5abb62d6b251b8e6d19c24c604343fb0acdbe16827e3ba6053685ba0ac95d7bf3745324e168ca86a63511c22f29a98c6f9bfebe08f3b7c19f4531b4aa577934 + checksum: d3c508f814305fdb5c6f409ec94694bbc053394fdccaa7e7b5ed0170dbea0a28fa8872318c0c47027490ed277c86664d34eee61f02cae7352d8f4260c47c1e4a languageName: node linkType: hard -"jest-config@npm:30.3.0": - version: 30.3.0 - resolution: "jest-config@npm:30.3.0" +"jest-config@npm:30.4.2": + version: 30.4.2 + resolution: "jest-config@npm:30.4.2" dependencies: "@babel/core": ^7.27.4 "@jest/get-type": 30.1.0 - "@jest/pattern": 30.0.1 - "@jest/test-sequencer": 30.3.0 - "@jest/types": 30.3.0 - babel-jest: 30.3.0 + "@jest/pattern": 30.4.0 + "@jest/test-sequencer": 30.4.1 + "@jest/types": 30.4.1 + babel-jest: 30.4.1 chalk: ^4.1.2 ci-info: ^4.2.0 deepmerge: ^4.3.1 glob: ^10.5.0 graceful-fs: ^4.2.11 - jest-circus: 30.3.0 - jest-docblock: 30.2.0 - jest-environment-node: 30.3.0 - jest-regex-util: 30.0.1 - jest-resolve: 30.3.0 - jest-runner: 30.3.0 - jest-util: 30.3.0 - jest-validate: 30.3.0 + jest-circus: 30.4.2 + jest-docblock: 30.4.0 + jest-environment-node: 30.4.1 + jest-regex-util: 30.4.0 + jest-resolve: 30.4.1 + jest-runner: 30.4.2 + jest-util: 30.4.1 + jest-validate: 30.4.1 parse-json: ^5.2.0 - pretty-format: 30.3.0 + pretty-format: 30.4.1 slash: ^3.0.0 strip-json-comments: ^3.1.1 peerDependencies: @@ -8660,94 +8661,94 @@ __metadata: optional: true ts-node: optional: true - checksum: a4f2f231ab674d4dc7f50de0c506854baefa3051467814a621cad38ae7024ac431a11d17e0cff4ef84d4edff7486a225a1a600df53fef054044c25e9157b9117 + checksum: 2637fff70f2f95e2efe1944f054d5852273712375ada9e2b2eedd9cb9ec119b496fb634f78d2be79151ac5c7991dd070a25d25fac48f44aa5e31f2db2d239998 languageName: node linkType: hard -"jest-diff@npm:30.3.0": - version: 30.3.0 - resolution: "jest-diff@npm:30.3.0" +"jest-diff@npm:30.4.1": + version: 30.4.1 + resolution: "jest-diff@npm:30.4.1" dependencies: - "@jest/diff-sequences": 30.3.0 + "@jest/diff-sequences": 30.4.0 "@jest/get-type": 30.1.0 chalk: ^4.1.2 - pretty-format: 30.3.0 - checksum: ad49d2c602a8006725cb507143ffa6f19eb355a56ad7dffc10361ce51f74dee103db9233e1a1aa7020d8dae138ec071034ba05391bc1b0e738b69a4a994dbf29 + pretty-format: 30.4.1 + checksum: f3e58eb102992d6cf2ab6737337f2f2ea7fdf28dbdaf2d7ed8ded08ef954a947ee7f641ef5e6e0f8b14b3c93c99c9428084e1d217e4febd2e3683373a6e57323 languageName: node linkType: hard -"jest-docblock@npm:30.2.0": - version: 30.2.0 - resolution: "jest-docblock@npm:30.2.0" +"jest-docblock@npm:30.4.0": + version: 30.4.0 + resolution: "jest-docblock@npm:30.4.0" dependencies: detect-newline: ^3.1.0 - checksum: 7074119d9919df539091e6b7f55c26858fafddb187ed1df90b2bc608544c2e6900384b97288ccd3b168f14bdcdf13281814337e1674a94d18991c8a0819aefad + checksum: 0ee25351ef941e832e53d10e74f34b38941b8f5fe750584661f6c5a115771818b081b8e39830c49d152fd361af81c7800c2d3a3c3a0e2dc742f7bfdbb6b1baaa languageName: node linkType: hard -"jest-each@npm:30.3.0": - version: 30.3.0 - resolution: "jest-each@npm:30.3.0" +"jest-each@npm:30.4.1": + version: 30.4.1 + resolution: "jest-each@npm:30.4.1" dependencies: "@jest/get-type": 30.1.0 - "@jest/types": 30.3.0 + "@jest/types": 30.4.1 chalk: ^4.1.2 - jest-util: 30.3.0 - pretty-format: 30.3.0 - checksum: 66b38115c82422eefeebe1077978906b8ba065fd669b87035c696af7b609d28e1ad83d3dc71311e16065d37232064cd12f1dbc5b9329dd8fad240afae68935a5 + jest-util: 30.4.1 + pretty-format: 30.4.1 + checksum: ef4c834eb2d0a0221651a75f5175932a98653c3f30cdf1956f2d4f61b5559cd33cf4ad51eb55a04c5e39f38c0025e2482a82fec5d569871b9d254f865ce18180 languageName: node linkType: hard -"jest-environment-jsdom@npm:^30.3.0": - version: 30.3.0 - resolution: "jest-environment-jsdom@npm:30.3.0" +"jest-environment-jsdom@npm:^30.4.1": + version: 30.4.1 + resolution: "jest-environment-jsdom@npm:30.4.1" dependencies: - "@jest/environment": 30.3.0 - "@jest/environment-jsdom-abstract": 30.3.0 + "@jest/environment": 30.4.1 + "@jest/environment-jsdom-abstract": 30.4.1 jsdom: ^26.1.0 peerDependencies: canvas: ^3.0.0 peerDependenciesMeta: canvas: optional: true - checksum: b5d4c9ccade6931854a174c4b6b1657cb1d9b66e519f820aebc8e349dfa6c445d94e5820bd2589d8c6b31ea37f1bd5731e6f643047b3e24c0182d4f7376aabe8 + checksum: 2ed0860e257d404622306823f18c15f0fe881fc1d16e1245434b54eb690fa0784cf54cd7eef74b2e9373e1699b1726a0fb69d60ae388cc78eb36968fe3fd0bf6 languageName: node linkType: hard -"jest-environment-node@npm:30.3.0": - version: 30.3.0 - resolution: "jest-environment-node@npm:30.3.0" +"jest-environment-node@npm:30.4.1": + version: 30.4.1 + resolution: "jest-environment-node@npm:30.4.1" dependencies: - "@jest/environment": 30.3.0 - "@jest/fake-timers": 30.3.0 - "@jest/types": 30.3.0 + "@jest/environment": 30.4.1 + "@jest/fake-timers": 30.4.1 + "@jest/types": 30.4.1 "@types/node": "*" - jest-mock: 30.3.0 - jest-util: 30.3.0 - jest-validate: 30.3.0 - checksum: ff8cc442be96ff5042469ae95f689116caaf11e29f975ec085c1ded7c030c7ddaa18885c58a6f1c79233c5bf170d7440216f23dad60f5610e24b5d6f870a085a + jest-mock: 30.4.1 + jest-util: 30.4.1 + jest-validate: 30.4.1 + checksum: 77267aaf6c6ae57d745dcbae6075563f58695a61b71d73a1617c49fd4747ed1cecb51f79697bc861e78d3a4abddfc1a8b6e4e1239a41896ba82a35cf5ef556e6 languageName: node linkType: hard -"jest-haste-map@npm:30.3.0": - version: 30.3.0 - resolution: "jest-haste-map@npm:30.3.0" +"jest-haste-map@npm:30.4.1": + version: 30.4.1 + resolution: "jest-haste-map@npm:30.4.1" dependencies: - "@jest/types": 30.3.0 + "@jest/types": 30.4.1 "@types/node": "*" anymatch: ^3.1.3 fb-watchman: ^2.0.2 fsevents: ^2.3.3 graceful-fs: ^4.2.11 - jest-regex-util: 30.0.1 - jest-util: 30.3.0 - jest-worker: 30.3.0 + jest-regex-util: 30.4.0 + jest-util: 30.4.1 + jest-worker: 30.4.1 picomatch: ^4.0.3 walker: ^1.0.8 dependenciesMeta: fsevents: optional: true - checksum: bb547ef3ad970dad434c0b884465719a946820e2cabed3ade4dcd50c89445c19a57f0385bc0b366ecff3c263c7da0b4d60c9e92c6357822cb6e7414a73d64ac8 + checksum: dcdc55a89b9bd1a2a13c1a2bc80100cd0a684b953704d2165f556702cf19a8348d4bcab569db619ce6065a8c745b19c3b7d586a8ac53108c9d7527c82926ab92 languageName: node linkType: hard @@ -8774,53 +8775,54 @@ __metadata: languageName: node linkType: hard -"jest-leak-detector@npm:30.3.0": - version: 30.3.0 - resolution: "jest-leak-detector@npm:30.3.0" +"jest-leak-detector@npm:30.4.1": + version: 30.4.1 + resolution: "jest-leak-detector@npm:30.4.1" dependencies: "@jest/get-type": 30.1.0 - pretty-format: 30.3.0 - checksum: 950ce3266067dd983f80231ce753fdfb9fe167d810b4507d84e674205c2cb96d37f38615ae502fa9277dde497ee52ce581656b48709aacf9502a4f0006bfab0e + pretty-format: 30.4.1 + checksum: 8c0945d1c73f6a2abde8660f7fc5693b344cd1f5fd66153c0c2d13007f8429486eb99ecf15ac68d3d4410534fd0fad1ed430c32a641cdac66e021dbd33204c9a languageName: node linkType: hard -"jest-matcher-utils@npm:30.3.0": - version: 30.3.0 - resolution: "jest-matcher-utils@npm:30.3.0" +"jest-matcher-utils@npm:30.4.1": + version: 30.4.1 + resolution: "jest-matcher-utils@npm:30.4.1" dependencies: "@jest/get-type": 30.1.0 chalk: ^4.1.2 - jest-diff: 30.3.0 - pretty-format: 30.3.0 - checksum: 3bc01ef81d001519fef75a32a0420c207664a829acbdc668bfa3c51e0a3ac2ddbb19c633e1e006ff63840bf231d915dfbe8dccef71e5ee842221ba1ff0da1946 + jest-diff: 30.4.1 + pretty-format: 30.4.1 + checksum: 18bc7a8ee2ce2fec06823e5ca231bd3c68f44f36143f6b738f6e191a60373dd3e5f595780f1b098d6945267b662368d1cd418f899fd6dbf07c3a9f3ba0673566 languageName: node linkType: hard -"jest-message-util@npm:30.3.0": - version: 30.3.0 - resolution: "jest-message-util@npm:30.3.0" +"jest-message-util@npm:30.4.1": + version: 30.4.1 + resolution: "jest-message-util@npm:30.4.1" dependencies: "@babel/code-frame": ^7.27.1 - "@jest/types": 30.3.0 + "@jest/types": 30.4.1 "@types/stack-utils": ^2.0.3 chalk: ^4.1.2 graceful-fs: ^4.2.11 + jest-util: 30.4.1 picomatch: ^4.0.3 - pretty-format: 30.3.0 + pretty-format: 30.4.1 slash: ^3.0.0 stack-utils: ^2.0.6 - checksum: 2d4c01e880ca312917b79699cea1e1d176940ce2e45f0ccb80399c1bc93825ca8e38955ada432f4427a165822be5a11fd9e46528e427308853f3c444741d5983 + checksum: 0361571c976e046d19569fa4d4617d1ef5926ed81710212869888059c5dd98ca13e77af2260fad2e756fe7041e1cf10f192cc0c38594b360643075dd42fa61c6 languageName: node linkType: hard -"jest-mock@npm:30.3.0": - version: 30.3.0 - resolution: "jest-mock@npm:30.3.0" +"jest-mock@npm:30.4.1": + version: 30.4.1 + resolution: "jest-mock@npm:30.4.1" dependencies: - "@jest/types": 30.3.0 + "@jest/types": 30.4.1 "@types/node": "*" - jest-util: 30.3.0 - checksum: bd015d5115ab74c40b37c9b9c46e49d16c8c9bdbfd50557a1805fe770a6422927a2f91252fc5f6aa8c061991be3c1bdbfc5f74ac26eb018311ec9ddb4e358df6 + jest-util: 30.4.1 + checksum: 98bf503f214dc0643317ceb3a05d63d18f915f3e30738e505568cf588dd2c4ac1f8c52014c396ce74cd1b3cc870e56ebfd0e3e369d88a052c046f031a5685725 languageName: node linkType: hard @@ -8836,10 +8838,10 @@ __metadata: languageName: node linkType: hard -"jest-regex-util@npm:30.0.1": - version: 30.0.1 - resolution: "jest-regex-util@npm:30.0.1" - checksum: fa8dac80c3e94db20d5e1e51d1bdf101cf5ede8f4e0b8f395ba8b8ea81e71804ffd747452a6bb6413032865de98ac656ef8ae43eddd18d980b6442a2764ed562 +"jest-regex-util@npm:30.4.0": + version: 30.4.0 + resolution: "jest-regex-util@npm:30.4.0" + checksum: 8664fcc1d07c8236a3bd012c0f06ae9d14d96e758b32ee340a3a7c4c326d0b5052d8c4ae4f4c4184f08bf78723d905352f22923647df9658ace3604f03bf074f languageName: node linkType: hard @@ -8850,132 +8852,132 @@ __metadata: languageName: node linkType: hard -"jest-resolve-dependencies@npm:30.3.0": - version: 30.3.0 - resolution: "jest-resolve-dependencies@npm:30.3.0" +"jest-resolve-dependencies@npm:30.4.2": + version: 30.4.2 + resolution: "jest-resolve-dependencies@npm:30.4.2" dependencies: - jest-regex-util: 30.0.1 - jest-snapshot: 30.3.0 - checksum: 3cecd5d952b03b38a425ccc6d4c98bba3f9413e268cc01a2724c2c91e45be7772ccf7ff38e17c417f3cc8a0ffaefd86cc2b61a7594d045dd2c4b06bdd031e882 + jest-regex-util: 30.4.0 + jest-snapshot: 30.4.1 + checksum: eba795d9ec140e4eb0107cd2cb716ef0881007df1ff8c023984e30b90e51aa8af17b1324f0c3196f77df8ff4cd64eafa020b14e539004bb6a21a76255be6d76c languageName: node linkType: hard -"jest-resolve@npm:30.3.0": - version: 30.3.0 - resolution: "jest-resolve@npm:30.3.0" +"jest-resolve@npm:30.4.1": + version: 30.4.1 + resolution: "jest-resolve@npm:30.4.1" dependencies: chalk: ^4.1.2 graceful-fs: ^4.2.11 - jest-haste-map: 30.3.0 + jest-haste-map: 30.4.1 jest-pnp-resolver: ^1.2.3 - jest-util: 30.3.0 - jest-validate: 30.3.0 + jest-util: 30.4.1 + jest-validate: 30.4.1 slash: ^3.0.0 unrs-resolver: ^1.7.11 - checksum: b48dae837c85251897d423fdd636c53e1490e04b2ca1bed3906d91abab1bb0c1045166337362dba197520a86bae9aace22875678361a8663149c85f6aaabcf18 + checksum: e1dffbcfbf5178b61633bfd83436a48c90b65e4d2e1c3863f148bfe52cccbee5bca244cb28c4b09bba49155a8e2191c9b2bbd25c47b9aedb73b967457fe56a77 languageName: node linkType: hard -"jest-runner@npm:30.3.0": - version: 30.3.0 - resolution: "jest-runner@npm:30.3.0" +"jest-runner@npm:30.4.2": + version: 30.4.2 + resolution: "jest-runner@npm:30.4.2" dependencies: - "@jest/console": 30.3.0 - "@jest/environment": 30.3.0 - "@jest/test-result": 30.3.0 - "@jest/transform": 30.3.0 - "@jest/types": 30.3.0 + "@jest/console": 30.4.1 + "@jest/environment": 30.4.1 + "@jest/test-result": 30.4.1 + "@jest/transform": 30.4.1 + "@jest/types": 30.4.1 "@types/node": "*" chalk: ^4.1.2 emittery: ^0.13.1 exit-x: ^0.2.2 graceful-fs: ^4.2.11 - jest-docblock: 30.2.0 - jest-environment-node: 30.3.0 - jest-haste-map: 30.3.0 - jest-leak-detector: 30.3.0 - jest-message-util: 30.3.0 - jest-resolve: 30.3.0 - jest-runtime: 30.3.0 - jest-util: 30.3.0 - jest-watcher: 30.3.0 - jest-worker: 30.3.0 + jest-docblock: 30.4.0 + jest-environment-node: 30.4.1 + jest-haste-map: 30.4.1 + jest-leak-detector: 30.4.1 + jest-message-util: 30.4.1 + jest-resolve: 30.4.1 + jest-runtime: 30.4.2 + jest-util: 30.4.1 + jest-watcher: 30.4.1 + jest-worker: 30.4.1 p-limit: ^3.1.0 source-map-support: 0.5.13 - checksum: 098ff88b4090d40a38901c314333ae9c7a6523b13e4e6378dbd323fd648fcb4948e6fab2d3eaa0e784f984910ace0c104eb8dced45e1f6fabd57a88daa90f4bd + checksum: 6fba662c5f1387931faf37e602f8b4a35d014b0f7de4b0e88bfd909c0d1c37019fc0c61967108b9fef1ba0f159592356cef2771397e797604921249730b6edde languageName: node linkType: hard -"jest-runtime@npm:30.3.0": - version: 30.3.0 - resolution: "jest-runtime@npm:30.3.0" +"jest-runtime@npm:30.4.2": + version: 30.4.2 + resolution: "jest-runtime@npm:30.4.2" dependencies: - "@jest/environment": 30.3.0 - "@jest/fake-timers": 30.3.0 - "@jest/globals": 30.3.0 + "@jest/environment": 30.4.1 + "@jest/fake-timers": 30.4.1 + "@jest/globals": 30.4.1 "@jest/source-map": 30.0.1 - "@jest/test-result": 30.3.0 - "@jest/transform": 30.3.0 - "@jest/types": 30.3.0 + "@jest/test-result": 30.4.1 + "@jest/transform": 30.4.1 + "@jest/types": 30.4.1 "@types/node": "*" chalk: ^4.1.2 cjs-module-lexer: ^2.1.0 collect-v8-coverage: ^1.0.2 glob: ^10.5.0 graceful-fs: ^4.2.11 - jest-haste-map: 30.3.0 - jest-message-util: 30.3.0 - jest-mock: 30.3.0 - jest-regex-util: 30.0.1 - jest-resolve: 30.3.0 - jest-snapshot: 30.3.0 - jest-util: 30.3.0 + jest-haste-map: 30.4.1 + jest-message-util: 30.4.1 + jest-mock: 30.4.1 + jest-regex-util: 30.4.0 + jest-resolve: 30.4.1 + jest-snapshot: 30.4.1 + jest-util: 30.4.1 slash: ^3.0.0 strip-bom: ^4.0.0 - checksum: 6f2ff5f3154d1481ef09ffc9760181b7636243c3bb6d1b3047f607a16f41dd248f6d00bed4cd846f1834ab0e58d48e5db444170f2f8b63e91ab36cfeaa6390a0 + checksum: e5b3dd744dae3ef21cbab2ca3b28baefeaaea7edbb908a261302b47a83288703c6f2f1ac0d46de42d880f72d4db2de9f36ed4fdd6da862acf8ff64dae21ac102 languageName: node linkType: hard -"jest-snapshot@npm:30.3.0": - version: 30.3.0 - resolution: "jest-snapshot@npm:30.3.0" +"jest-snapshot@npm:30.4.1": + version: 30.4.1 + resolution: "jest-snapshot@npm:30.4.1" dependencies: "@babel/core": ^7.27.4 "@babel/generator": ^7.27.5 "@babel/plugin-syntax-jsx": ^7.27.1 "@babel/plugin-syntax-typescript": ^7.27.1 "@babel/types": ^7.27.3 - "@jest/expect-utils": 30.3.0 + "@jest/expect-utils": 30.4.1 "@jest/get-type": 30.1.0 - "@jest/snapshot-utils": 30.3.0 - "@jest/transform": 30.3.0 - "@jest/types": 30.3.0 + "@jest/snapshot-utils": 30.4.1 + "@jest/transform": 30.4.1 + "@jest/types": 30.4.1 babel-preset-current-node-syntax: ^1.2.0 chalk: ^4.1.2 - expect: 30.3.0 + expect: 30.4.1 graceful-fs: ^4.2.11 - jest-diff: 30.3.0 - jest-matcher-utils: 30.3.0 - jest-message-util: 30.3.0 - jest-util: 30.3.0 - pretty-format: 30.3.0 + jest-diff: 30.4.1 + jest-matcher-utils: 30.4.1 + jest-message-util: 30.4.1 + jest-util: 30.4.1 + pretty-format: 30.4.1 semver: ^7.7.2 synckit: ^0.11.8 - checksum: cc7b8562eff4da6ebedfad3f9f672433da3c5faf56036d7baccaf095b22112788a4d9614caf8b6e5055f266e55871cdf4672787c2802360cfd1d84dadcdd18d5 + checksum: 3a95853867e48ac5d44742a600f80837fabb9bbcf4ee25b9c99709812c6776dfb0e2ec98d0316dc2753b577b20d0d6be46a3610b134923c6855363dcb57b44d2 languageName: node linkType: hard -"jest-util@npm:30.3.0": - version: 30.3.0 - resolution: "jest-util@npm:30.3.0" +"jest-util@npm:30.4.1": + version: 30.4.1 + resolution: "jest-util@npm:30.4.1" dependencies: - "@jest/types": 30.3.0 + "@jest/types": 30.4.1 "@types/node": "*" chalk: ^4.1.2 ci-info: ^4.2.0 graceful-fs: ^4.2.11 picomatch: ^4.0.3 - checksum: 27309dd3cb6f495c005bddf5910acabcdae4919f4646bd0d0ea66a8c60d810cc111665de99cc4f6420dd1a3e695f274e9def6301ef3b22bcce67d4541e2d53e4 + checksum: 5b1b3e5cca87151f31dc9636a74ef2e78823f0bcd7e636a1bdc3e57645bf5970c01ff476db9156dea198984bd67415520c068bc5b3eddd464a2e6e9696308ecf languageName: node linkType: hard @@ -8993,46 +8995,46 @@ __metadata: languageName: node linkType: hard -"jest-validate@npm:30.3.0": - version: 30.3.0 - resolution: "jest-validate@npm:30.3.0" +"jest-validate@npm:30.4.1": + version: 30.4.1 + resolution: "jest-validate@npm:30.4.1" dependencies: "@jest/get-type": 30.1.0 - "@jest/types": 30.3.0 + "@jest/types": 30.4.1 camelcase: ^6.3.0 chalk: ^4.1.2 leven: ^3.1.0 - pretty-format: 30.3.0 - checksum: 5a76ae7f253da5707065225416b75470aa9445b32e01a7e559399a7971e5ccfdf71f4768e45c33565e4895df4998bb8a292dda7be1c723318c5c6ab334cae7da + pretty-format: 30.4.1 + checksum: c533a0c6021e5c630b78749d5be9f21bb0f91fa8b9ce029cfe22b8c8162db3046fa236de62752a35a35ab5b65da099ad5f2b0240c055cddb05460ddf45bb5c1e languageName: node linkType: hard -"jest-watcher@npm:30.3.0": - version: 30.3.0 - resolution: "jest-watcher@npm:30.3.0" +"jest-watcher@npm:30.4.1": + version: 30.4.1 + resolution: "jest-watcher@npm:30.4.1" dependencies: - "@jest/test-result": 30.3.0 - "@jest/types": 30.3.0 + "@jest/test-result": 30.4.1 + "@jest/types": 30.4.1 "@types/node": "*" ansi-escapes: ^4.3.2 chalk: ^4.1.2 emittery: ^0.13.1 - jest-util: 30.3.0 + jest-util: 30.4.1 string-length: ^4.0.2 - checksum: c3aad544fc29bc17f3d4cf6e6d6f1180e6d1eae36881968a2da16fc14ac03b7a10761e77971d3d12dba1852c34e34907c81eab5be8757568cb9502d204942fbd + checksum: 843fc1cda04b2edb4d618fd945fb515b4a6c523f6d23b5a576735ed251bef2ea80d9d6a9864271e92caa9f1467283724c2d39b80d73289b8d95e378b89dcabe5 languageName: node linkType: hard -"jest-worker@npm:30.3.0": - version: 30.3.0 - resolution: "jest-worker@npm:30.3.0" +"jest-worker@npm:30.4.1": + version: 30.4.1 + resolution: "jest-worker@npm:30.4.1" dependencies: "@types/node": "*" "@ungap/structured-clone": ^1.3.0 - jest-util: 30.3.0 + jest-util: 30.4.1 merge-stream: ^2.0.0 supports-color: ^8.1.1 - checksum: 886803abcda389324aa824d1c0b800f7acd2eeb70b8ff364cecae22019dfd34157a99fe37e465b7a85bd28746591cee04ea85f2dc86002c44583dd8cf1250d20 + checksum: 1a30619cf0a66efc1f533b155152f63ba3d4f4adb5085f1e0941065bf914f7d4fb41fd75ada1d606ab8160d58ffa64010ed3236eda203ddce283692a05f8f2e5 languageName: node linkType: hard @@ -9059,14 +9061,14 @@ __metadata: languageName: node linkType: hard -"jest@npm:^30.3.0": - version: 30.3.0 - resolution: "jest@npm:30.3.0" +"jest@npm:^30.4.2": + version: 30.4.2 + resolution: "jest@npm:30.4.2" dependencies: - "@jest/core": 30.3.0 - "@jest/types": 30.3.0 + "@jest/core": 30.4.2 + "@jest/types": 30.4.1 import-local: ^3.2.0 - jest-cli: 30.3.0 + jest-cli: 30.4.2 peerDependencies: node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 peerDependenciesMeta: @@ -9074,7 +9076,7 @@ __metadata: optional: true bin: jest: ./bin/jest.js - checksum: b79fafc8e06b9b5727f7b13c0e230f904c40c642d663a0f1f58de358dda4ba5dcbbc5ae398a461296b77a7f5d9d75f5d8dc659905c8183b21ebf3584c882e547 + checksum: 7cae567b887e5d2f8d667b90b16c8e3e909d49bb23030a4d618b20d854fb44e9631a14aaf978e6d8399d6c6ced5a5633e99b759d1d8d807e137d6a8e96aa7656 languageName: node linkType: hard @@ -10824,14 +10826,15 @@ __metadata: languageName: node linkType: hard -"pretty-format@npm:30.3.0": - version: 30.3.0 - resolution: "pretty-format@npm:30.3.0" +"pretty-format@npm:30.4.1": + version: 30.4.1 + resolution: "pretty-format@npm:30.4.1" dependencies: - "@jest/schemas": 30.0.5 + "@jest/schemas": 30.4.1 ansi-styles: ^5.2.0 - react-is: ^18.3.1 - checksum: 99bb09b51551fb710143a2c0b8270acc2f7723d51cdb5824fe55a0061e04af8bf07c47acd565121cb5b266dfc7a3ecfe77bf85b4f96aacbbeb6f2df0ba246a9c + react-is-18: "npm:react-is@^18.3.1" + react-is-19: "npm:react-is@^19.2.5" + checksum: 9602635027892d7a2f430b0a51972780226d30ce4072643349ad376ccee967539eb8180a656976976c0673d550604847da638b992eefc95c84bab7cebdf9faba languageName: node linkType: hard @@ -11050,6 +11053,20 @@ __metadata: languageName: node linkType: hard +"react-is-18@npm:react-is@^18.3.1": + version: 18.3.1 + resolution: "react-is@npm:18.3.1" + checksum: e20fe84c86ff172fc8d898251b7cc2c43645d108bf96d0b8edf39b98f9a2cae97b40520ee7ed8ee0085ccc94736c4886294456033304151c3f94978cec03df21 + languageName: node + linkType: hard + +"react-is-19@npm:react-is@^19.2.5": + version: 19.2.7 + resolution: "react-is@npm:19.2.7" + checksum: 148ee03b481ace8370cb9b96de386598423ed44ad36090c45ce3f905aec496db6f2675da720bbe43f39d66c43c9a16757cb71e9e55217825707dae97f0cf200f + languageName: node + linkType: hard + "react-is@npm:19.1.0": version: 19.1.0 resolution: "react-is@npm:19.1.0" From 2bac4c6435b6225f29a7d2fd26542148ec320fbd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Jun 2026 20:15:27 -0400 Subject: [PATCH 11/39] build(deps): bump the babel group across 1 directory with 5 updates (#1723) Bumps the babel group with 5 updates in the / directory: | Package | From | To | | --- | --- | --- | | [@babel/runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-runtime) | `7.29.2` | `7.29.7` | | [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) | `7.29.0` | `7.29.7` | | [@babel/eslint-parser](https://github.com/babel/babel/tree/HEAD/eslint/babel-eslint-parser) | `7.28.6` | `7.29.7` | | [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) | `7.29.3` | `7.29.7` | | [@babel/preset-react](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-react) | `7.28.5` | `7.29.7` | Updates `@babel/runtime` from 7.29.2 to 7.29.7 - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v7.29.7/packages/babel-runtime) Updates `@babel/core` from 7.29.0 to 7.29.7 - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v7.29.7/packages/babel-core) Updates `@babel/eslint-parser` from 7.28.6 to 7.29.7 - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v7.29.7/eslint/babel-eslint-parser) Updates `@babel/preset-env` from 7.29.3 to 7.29.7 - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v7.29.7/packages/babel-preset-env) Updates `@babel/preset-react` from 7.28.5 to 7.29.7 - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v7.29.7/packages/babel-preset-react) --- updated-dependencies: - dependency-name: "@babel/core" dependency-version: 7.29.7 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: babel - dependency-name: "@babel/eslint-parser" dependency-version: 7.29.7 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: babel - dependency-name: "@babel/preset-env" dependency-version: 7.29.7 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: babel - dependency-name: "@babel/preset-react" dependency-version: 7.29.7 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: babel - dependency-name: "@babel/runtime" dependency-version: 7.29.7 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: babel ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 10 +- yarn.lock | 1249 ++++++++++++++++++++++++++------------------------ 2 files changed, 667 insertions(+), 592 deletions(-) diff --git a/package.json b/package.json index d64a254fe..cf85c4322 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ ] }, "dependencies": { - "@babel/runtime": "^7.29.2", + "@babel/runtime": "^7.29.7", "@emotion/react": "^11.14.0", "@emotion/styled": "^11.14.1", "@fortawesome/fontawesome-svg-core": "^7.2.0", @@ -49,11 +49,11 @@ "react-tooltip": "^5.28.0" }, "devDependencies": { - "@babel/core": "^7.29.0", - "@babel/eslint-parser": "^7.28.6", + "@babel/core": "^7.29.7", + "@babel/eslint-parser": "^7.29.7", "@babel/plugin-proposal-class-properties": "^7.18.6", - "@babel/preset-env": "^7.29.3", - "@babel/preset-react": "^7.28.5", + "@babel/preset-env": "^7.29.7", + "@babel/preset-react": "^7.29.7", "@eslint/compat": "^1.2.9", "@testing-library/dom": "^10.4.0", "@testing-library/react": "^16.0.1", diff --git a/yarn.lock b/yarn.lock index faf4bf67c..189a8b0fc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -29,14 +29,14 @@ __metadata: languageName: node linkType: hard -"@babel/code-frame@npm:^7.28.6, @babel/code-frame@npm:^7.29.0": - version: 7.29.0 - resolution: "@babel/code-frame@npm:7.29.0" +"@babel/code-frame@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/code-frame@npm:7.29.7" dependencies: - "@babel/helper-validator-identifier": ^7.28.5 + "@babel/helper-validator-identifier": ^7.29.7 js-tokens: ^4.0.0 picocolors: ^1.1.1 - checksum: 39f5b303757e4d63bbff8133e251094cd4f952b46e3fa9febc7368d907583911d6a1eded6090876dc1feeff5cf6e134fb19b706f8d58d26c5402cd50e5e1aeb2 + checksum: 21b12fe2356e36f6cc3cd8a3721f878bfeea80ce38356979a0518b47b3aafdcc0bd263da75ccc9d51c64d40b1b6df00e768ce2446acb0b7cbec0ae8f905663ad languageName: node linkType: hard @@ -54,10 +54,10 @@ __metadata: languageName: node linkType: hard -"@babel/compat-data@npm:^7.29.3": - version: 7.29.3 - resolution: "@babel/compat-data@npm:7.29.3" - checksum: 977192bab334f66bc8150026340a33ed318c1a7ce18a9323f4c1b86f8ed1d8645bfe5600242bf682717c05c46a4ff06225242207c1d599f4296914b9b4e3efb5 +"@babel/compat-data@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/compat-data@npm:7.29.7" + checksum: 4424f8fb72f61657c8e811bdf7e5c69af212a15fe362711162b2e00b82f0e0588fb8259ecd9a70c5490562bf51d408b0cb92f277ead71a2390ddddfe7283b35d languageName: node linkType: hard @@ -84,32 +84,32 @@ __metadata: languageName: node linkType: hard -"@babel/core@npm:^7.29.0": - version: 7.29.0 - resolution: "@babel/core@npm:7.29.0" +"@babel/core@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/core@npm:7.29.7" dependencies: - "@babel/code-frame": ^7.29.0 - "@babel/generator": ^7.29.0 - "@babel/helper-compilation-targets": ^7.28.6 - "@babel/helper-module-transforms": ^7.28.6 - "@babel/helpers": ^7.28.6 - "@babel/parser": ^7.29.0 - "@babel/template": ^7.28.6 - "@babel/traverse": ^7.29.0 - "@babel/types": ^7.29.0 + "@babel/code-frame": ^7.29.7 + "@babel/generator": ^7.29.7 + "@babel/helper-compilation-targets": ^7.29.7 + "@babel/helper-module-transforms": ^7.29.7 + "@babel/helpers": ^7.29.7 + "@babel/parser": ^7.29.7 + "@babel/template": ^7.29.7 + "@babel/traverse": ^7.29.7 + "@babel/types": ^7.29.7 "@jridgewell/remapping": ^2.3.5 convert-source-map: ^2.0.0 debug: ^4.1.0 gensync: ^1.0.0-beta.2 json5: ^2.2.3 semver: ^6.3.1 - checksum: 85e1df6e213382c46dee27bcd07ed9202fa108a85bb74eb37be656308fd949349171ad2aa17cc84cf0720c908dc9ea6309d25e64d2a7fcdaa63721ce0c67c10b + checksum: 95149e98ffde5b9d903459c284fbcf1f9ad8b3a833d69fdfe1aa7185821a102af1925324fe2892caf4b643b151c1dc948510d1e25a5e3c6c6c6f17f6712eb38e languageName: node linkType: hard -"@babel/eslint-parser@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/eslint-parser@npm:7.28.6" +"@babel/eslint-parser@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/eslint-parser@npm:7.29.7" dependencies: "@nicolo-ribaudo/eslint-scope-5-internals": 5.1.1-v1 eslint-visitor-keys: ^2.1.0 @@ -117,7 +117,7 @@ __metadata: peerDependencies: "@babel/core": ^7.11.0 eslint: ^7.5.0 || ^8.0.0 || ^9.0.0 - checksum: 6d789f16842c6f47a6a15f8159ef822e4bf75e8d15f85be2a813098ca4ba49703590ff2cdd56c78cc8816f5779b687cd6245ada4049c25e923e8e40132ace501 + checksum: def39180054d2bdf2ab6e119d50e2746a60531a410496e973c08f5f16daa167722d7c8be96d759837a79b3a763d3bf9b188a0c55671e08d0c1e73a81617e9aa1 languageName: node linkType: hard @@ -134,16 +134,16 @@ __metadata: languageName: node linkType: hard -"@babel/generator@npm:^7.29.0": - version: 7.29.0 - resolution: "@babel/generator@npm:7.29.0" +"@babel/generator@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/generator@npm:7.29.7" dependencies: - "@babel/parser": ^7.29.0 - "@babel/types": ^7.29.0 + "@babel/parser": ^7.29.7 + "@babel/types": ^7.29.7 "@jridgewell/gen-mapping": ^0.3.12 "@jridgewell/trace-mapping": ^0.3.28 jsesc: ^3.0.2 - checksum: 7d338a9278a401764605fac87f3e223c70b50be15ebd6cf856249db9554133a620cf841ff62e4dfcc46ca59f2c16b62a2ce12891d48e47ed987f19bfbfd5469e + checksum: 6bb8f4dc0641dca19e81f5daab37ed1a1f5a78e4d702eb79a4275739f773975134e250090c182cf1eea35d9bd65e634b9d9babf66600ffdcf8ac62fa40f3b980 languageName: node linkType: hard @@ -156,7 +156,16 @@ __metadata: languageName: node linkType: hard -"@babel/helper-compilation-targets@npm:^7.27.1, @babel/helper-compilation-targets@npm:^7.27.2": +"@babel/helper-annotate-as-pure@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/helper-annotate-as-pure@npm:7.29.7" + dependencies: + "@babel/types": ^7.29.7 + checksum: acd9e128de634a5144b5d622357d018fa616de45f64c74e42007c048dd15d0a0be213f4d5a2bf02307bdaddf053791b87900a99d183de828c08dc3b556329009 + languageName: node + linkType: hard + +"@babel/helper-compilation-targets@npm:^7.27.2": version: 7.27.2 resolution: "@babel/helper-compilation-targets@npm:7.27.2" dependencies: @@ -182,6 +191,19 @@ __metadata: languageName: node linkType: hard +"@babel/helper-compilation-targets@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/helper-compilation-targets@npm:7.29.7" + dependencies: + "@babel/compat-data": ^7.29.7 + "@babel/helper-validator-option": ^7.29.7 + browserslist: ^4.24.0 + lru-cache: ^5.1.1 + semver: ^6.3.1 + checksum: f60a943937f4eba0e671aa28551cb45569fd081c1e30a52ede167860475dc0417f3dbdf2a0fa3f086965595c7070aa76308da60cc0319860de05db4ed2a431f7 + languageName: node + linkType: hard + "@babel/helper-create-class-features-plugin@npm:^7.18.6": version: 7.28.3 resolution: "@babel/helper-create-class-features-plugin@npm:7.28.3" @@ -199,24 +221,24 @@ __metadata: languageName: node linkType: hard -"@babel/helper-create-class-features-plugin@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/helper-create-class-features-plugin@npm:7.28.6" +"@babel/helper-create-class-features-plugin@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/helper-create-class-features-plugin@npm:7.29.7" dependencies: - "@babel/helper-annotate-as-pure": ^7.27.3 - "@babel/helper-member-expression-to-functions": ^7.28.5 - "@babel/helper-optimise-call-expression": ^7.27.1 - "@babel/helper-replace-supers": ^7.28.6 - "@babel/helper-skip-transparent-expression-wrappers": ^7.27.1 - "@babel/traverse": ^7.28.6 + "@babel/helper-annotate-as-pure": ^7.29.7 + "@babel/helper-member-expression-to-functions": ^7.29.7 + "@babel/helper-optimise-call-expression": ^7.29.7 + "@babel/helper-replace-supers": ^7.29.7 + "@babel/helper-skip-transparent-expression-wrappers": ^7.29.7 + "@babel/traverse": ^7.29.7 semver: ^6.3.1 peerDependencies: "@babel/core": ^7.0.0 - checksum: f886ab302a83f8e410384aa635806b22374897fd9e3387c737ab9d91d1214bf9f7e57ae92619bd25dea63c9c0a49b25b44eb807873332e0eb9549219adc73639 + checksum: c954e4bfe423a277cdcbad64344637cf696ddcd80085fce5f284b02a0c700af0d2d7b61468a06d9e296e948de60ece138921b65564aec023a9d9594f5d9fe18d languageName: node linkType: hard -"@babel/helper-create-regexp-features-plugin@npm:^7.18.6, @babel/helper-create-regexp-features-plugin@npm:^7.27.1": +"@babel/helper-create-regexp-features-plugin@npm:^7.18.6": version: 7.27.1 resolution: "@babel/helper-create-regexp-features-plugin@npm:7.27.1" dependencies: @@ -229,16 +251,16 @@ __metadata: languageName: node linkType: hard -"@babel/helper-create-regexp-features-plugin@npm:^7.28.5": - version: 7.28.5 - resolution: "@babel/helper-create-regexp-features-plugin@npm:7.28.5" +"@babel/helper-create-regexp-features-plugin@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/helper-create-regexp-features-plugin@npm:7.29.7" dependencies: - "@babel/helper-annotate-as-pure": ^7.27.3 + "@babel/helper-annotate-as-pure": ^7.29.7 regexpu-core: ^6.3.1 semver: ^6.3.1 peerDependencies: "@babel/core": ^7.0.0 - checksum: de202103e6ff8cd8da0d62eb269fcceb29857f3fa16173f0ff38188fd514e9ad4901aef1d590ff8ba25381644b42eaf70ad9ba91fda59fe7aa6a5e694cdde267 + checksum: 702a34db6c064a2c26675b717b3af88b8acaeb5341e2285792a873a67a16ec4cbe987ba72e055db198b2e03ead05600d8c9c0c1e7436708e95865bbfb3516026 languageName: node linkType: hard @@ -264,6 +286,13 @@ __metadata: languageName: node linkType: hard +"@babel/helper-globals@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/helper-globals@npm:7.29.7" + checksum: 6deaf9846a415c7f110ac153e8c3d81e3543c9b685aa9fd9a59b4235f402e2b760129d3df49466daea9162f0cf73ff98a0ec7f180448a3449ca14ae5e1117b42 + languageName: node + linkType: hard + "@babel/helper-member-expression-to-functions@npm:^7.27.1": version: 7.27.1 resolution: "@babel/helper-member-expression-to-functions@npm:7.27.1" @@ -274,13 +303,13 @@ __metadata: languageName: node linkType: hard -"@babel/helper-member-expression-to-functions@npm:^7.28.5": - version: 7.28.5 - resolution: "@babel/helper-member-expression-to-functions@npm:7.28.5" +"@babel/helper-member-expression-to-functions@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/helper-member-expression-to-functions@npm:7.29.7" dependencies: - "@babel/traverse": ^7.28.5 - "@babel/types": ^7.28.5 - checksum: 447d385233bae2eea713df1785f819b5a5ca272950740da123c42d23f491045120f0fbbb5609c091f7a9bbd40f289a442846dde0cb1bf0c59440fa093690cf7c + "@babel/traverse": ^7.29.7 + "@babel/types": ^7.29.7 + checksum: 79d5f095b4bafadff3d1ec316d9f17ec85940fece957db62dd523b08e142da73c53180d1bce2fdc4d523e3889bb01b39bea70ad968b6e2f4dbdc66ebd1055b8a languageName: node linkType: hard @@ -294,17 +323,17 @@ __metadata: languageName: node linkType: hard -"@babel/helper-module-imports@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/helper-module-imports@npm:7.28.6" +"@babel/helper-module-imports@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/helper-module-imports@npm:7.29.7" dependencies: - "@babel/traverse": ^7.28.6 - "@babel/types": ^7.28.6 - checksum: 437513aa029898b588a38f7991d7656c539b22f595207d85d0c407240c9e3f2aff8b9d0d7115fdedc91e7fdce4465100549a052024e2fba6a810bcbb7584296b + "@babel/traverse": ^7.29.7 + "@babel/types": ^7.29.7 + checksum: ad5a768fc9c162620b7f5b7645c6c2efee1e6f9df432bb79651888661a7e4cd91dac7192f3ddcfd6de4778a089e9fb30fafae768156aa73a07eeca425f64e849 languageName: node linkType: hard -"@babel/helper-module-transforms@npm:^7.27.1, @babel/helper-module-transforms@npm:^7.28.3": +"@babel/helper-module-transforms@npm:^7.28.3": version: 7.28.3 resolution: "@babel/helper-module-transforms@npm:7.28.3" dependencies: @@ -317,16 +346,16 @@ __metadata: languageName: node linkType: hard -"@babel/helper-module-transforms@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/helper-module-transforms@npm:7.28.6" +"@babel/helper-module-transforms@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/helper-module-transforms@npm:7.29.7" dependencies: - "@babel/helper-module-imports": ^7.28.6 - "@babel/helper-validator-identifier": ^7.28.5 - "@babel/traverse": ^7.28.6 + "@babel/helper-module-imports": ^7.29.7 + "@babel/helper-validator-identifier": ^7.29.7 + "@babel/traverse": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0 - checksum: 522f7d1d08b5e2ccd4ec912aca879bd1506af78d1fb30f46e3e6b4bb69c6ae6ab4e379a879723844230d27dc6d04a55b03f5215cd3141b7a2b40bb4a02f71a9f + checksum: 484f6d02975d304f680d44e331d4b832d67e51917483985eab7b853664452b5a627366e7a9d421200ec772a123213a591e28b40636566afeac189411ba3f45a8 languageName: node linkType: hard @@ -339,6 +368,15 @@ __metadata: languageName: node linkType: hard +"@babel/helper-optimise-call-expression@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/helper-optimise-call-expression@npm:7.29.7" + dependencies: + "@babel/types": ^7.29.7 + checksum: 6b477e01b403fd48349336cb1d94722bff4fa54af2841b5fa950c557b796f4ecc14724052252ed1362ccfc23d1c09c54dc03e182fea59d3dc5bd69f8c626ba25 + languageName: node + linkType: hard + "@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.10.4, @babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.14.5, @babel/helper-plugin-utils@npm:^7.18.6, @babel/helper-plugin-utils@npm:^7.27.1, @babel/helper-plugin-utils@npm:^7.8.0": version: 7.27.1 resolution: "@babel/helper-plugin-utils@npm:7.27.1" @@ -353,16 +391,23 @@ __metadata: languageName: node linkType: hard -"@babel/helper-remap-async-to-generator@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/helper-remap-async-to-generator@npm:7.27.1" +"@babel/helper-plugin-utils@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/helper-plugin-utils@npm:7.29.7" + checksum: b0a183abcc6670afa4861425fa428217d8ebadce062d5b43117919e8715f820080fd63bbfcf0e43c6e0e7d21a96b21f635c46dda80bdb0ce7e8a762ebee1d8d9 + languageName: node + linkType: hard + +"@babel/helper-remap-async-to-generator@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/helper-remap-async-to-generator@npm:7.29.7" dependencies: - "@babel/helper-annotate-as-pure": ^7.27.1 - "@babel/helper-wrap-function": ^7.27.1 - "@babel/traverse": ^7.27.1 + "@babel/helper-annotate-as-pure": ^7.29.7 + "@babel/helper-wrap-function": ^7.29.7 + "@babel/traverse": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0 - checksum: 0747397ba013f87dbf575454a76c18210d61c7c9af0f697546b4bcac670b54ddc156330234407b397f0c948738c304c228e0223039bc45eab4fbf46966a5e8cc + checksum: 98338ad6e34ebb4be2dc23f8d9199d28d6d8ac6a2ce8b90fe9efdf3595b39748321528d9f2540ec0586a6e45f7c84f5f623fbf980c5efa7fa9ba7ce837ea4b20 languageName: node linkType: hard @@ -379,16 +424,16 @@ __metadata: languageName: node linkType: hard -"@babel/helper-replace-supers@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/helper-replace-supers@npm:7.28.6" +"@babel/helper-replace-supers@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/helper-replace-supers@npm:7.29.7" dependencies: - "@babel/helper-member-expression-to-functions": ^7.28.5 - "@babel/helper-optimise-call-expression": ^7.27.1 - "@babel/traverse": ^7.28.6 + "@babel/helper-member-expression-to-functions": ^7.29.7 + "@babel/helper-optimise-call-expression": ^7.29.7 + "@babel/traverse": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0 - checksum: aa6530a52010883b6be88465e3b9e789509786a40203650a23a51c315f7442b196e5925fb8e2d66d1e3dc2c604cdc817bd8c5c170dbb322ab5ebc7486fd8a022 + checksum: f7eb9a6b035d9d45250c880eb09605f95998998e828ec90759ed45764fe0abeee583419969de8b8dee551163dff914c9fc6ace90c1d819c56c23146f8df525db languageName: node linkType: hard @@ -402,6 +447,16 @@ __metadata: languageName: node linkType: hard +"@babel/helper-skip-transparent-expression-wrappers@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/helper-skip-transparent-expression-wrappers@npm:7.29.7" + dependencies: + "@babel/traverse": ^7.29.7 + "@babel/types": ^7.29.7 + checksum: a5800bfcdca6cef7f6fe33ac02a0f05ff33da9746f97806553f249733f7ba8400290a17f3831d7faa5d91656f254ab749931f53c8a29f301d958d7dd00499637 + languageName: node + linkType: hard + "@babel/helper-string-parser@npm:^7.27.1": version: 7.27.1 resolution: "@babel/helper-string-parser@npm:7.27.1" @@ -409,6 +464,13 @@ __metadata: languageName: node linkType: hard +"@babel/helper-string-parser@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/helper-string-parser@npm:7.29.7" + checksum: 4c229d2c2296b6c94439e87ecddf3a93cee3ffd2d4cee0b4c28079275bed3de4e02cd943e4cb06036d1d9407549c4e3423006b61a46215c482fce902ee02bc0b + languageName: node + linkType: hard + "@babel/helper-validator-identifier@npm:^7.27.1, @babel/helper-validator-identifier@npm:^7.28.5": version: 7.28.5 resolution: "@babel/helper-validator-identifier@npm:7.28.5" @@ -416,6 +478,13 @@ __metadata: languageName: node linkType: hard +"@babel/helper-validator-identifier@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/helper-validator-identifier@npm:7.29.7" + checksum: cc7779e96fe9c9478c96ca4bf04fc338b95b501aa5abe78178307dea282d4a5dc23d443efb12dde8e8c5636d03dd00e443532e6ed7f15fa7977349af1f87ba4d + languageName: node + linkType: hard + "@babel/helper-validator-option@npm:^7.27.1": version: 7.27.1 resolution: "@babel/helper-validator-option@npm:7.27.1" @@ -423,14 +492,21 @@ __metadata: languageName: node linkType: hard -"@babel/helper-wrap-function@npm:^7.27.1": - version: 7.28.3 - resolution: "@babel/helper-wrap-function@npm:7.28.3" +"@babel/helper-validator-option@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/helper-validator-option@npm:7.29.7" + checksum: aeb6aa966f59300d3cc2fea7c68e1dfd7ad011fc10e535c8e2b2de3094b27c859428dc7220f16420350f8b1cde99da120b673be04bcb0c2f37b56258c96bed58 + languageName: node + linkType: hard + +"@babel/helper-wrap-function@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/helper-wrap-function@npm:7.29.7" dependencies: - "@babel/template": ^7.27.2 - "@babel/traverse": ^7.28.3 - "@babel/types": ^7.28.2 - checksum: 0ebdfdc918fdd0c1cf6ff15ba4c664974d0cdf21a017af560d58b00c379df3bf2e55f13a44fe3225668bca169da174f6cb97a96c4e987fb728fdb8f9a39db302 + "@babel/template": ^7.29.7 + "@babel/traverse": ^7.29.7 + "@babel/types": ^7.29.7 + checksum: 2e6dfca94a10a3672a6b0ff337c80f27d7c66f3ea110969e833529a2d5bfbb5e53ab40abf6fad4657b8f810fcab2e3d56998f8da89bfe82a58267c5e8bc06e9a languageName: node linkType: hard @@ -444,13 +520,13 @@ __metadata: languageName: node linkType: hard -"@babel/helpers@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/helpers@npm:7.28.6" +"@babel/helpers@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/helpers@npm:7.29.7" dependencies: - "@babel/template": ^7.28.6 - "@babel/types": ^7.28.6 - checksum: 4f3d555ec20dde40a2fcb244c86bfd9ec007b57ec9b30a9d04334c1ea2c1670bb82c151024124e1ab27ccf0b1f5ad30167633457a7c9ffbf4064fad2643f12fc + "@babel/template": ^7.29.7 + "@babel/types": ^7.29.7 + checksum: b5c4ed0ce5983c5599cd01b3948444b77ba2fa47bf6282a82afdcbe45eb8cc5b7986194e3920ef2760f533c6a775504e6b00a66960c0a3bc52909920b8433908 languageName: node linkType: hard @@ -465,85 +541,85 @@ __metadata: languageName: node linkType: hard -"@babel/parser@npm:^7.28.6, @babel/parser@npm:^7.29.0": - version: 7.29.0 - resolution: "@babel/parser@npm:7.29.0" +"@babel/parser@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/parser@npm:7.29.7" dependencies: - "@babel/types": ^7.29.0 + "@babel/types": ^7.29.7 bin: parser: ./bin/babel-parser.js - checksum: b4a1bd3cf46712e439286db9a4105dfa741b5a7720fa1f38f33719cf4f1da9df9fc5b6686128890bd6a62debba287d8d472af153dd629fd4a0a44fe55413cd68 + checksum: 56f4c32a371004d3becd0a960a85a3bba4ec4df73d5e202aa3fe6473328b243162c6be9a510be1c12ed1825f5ce9ff1ea5cc357298631e8acf2e5b8da9f5a961 languageName: node linkType: hard -"@babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:^7.28.5": - version: 7.28.5 - resolution: "@babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:7.28.5" +"@babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:7.29.7" dependencies: - "@babel/helper-plugin-utils": ^7.27.1 - "@babel/traverse": ^7.28.5 + "@babel/helper-plugin-utils": ^7.29.7 + "@babel/traverse": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0 - checksum: 749b40a963d5633f554cad0336245cb6c1c1393c70a3fddcf302d86a1a42b35efdd2ed62056b88db66f3900887ae1cee9a3eeec89799c22e0cf65059f0dfd142 + checksum: 83cca77d175f3e66460a004648c8a645da880d5a9db96b03abd433e05bc4357aec0418d17b05fbfecfa679438b8eb8d8adc71b8f4db86cfaf6e6b0373b39a05e languageName: node linkType: hard -"@babel/plugin-bugfix-safari-class-field-initializer-scope@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-bugfix-safari-class-field-initializer-scope@npm:7.27.1" +"@babel/plugin-bugfix-safari-class-field-initializer-scope@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-bugfix-safari-class-field-initializer-scope@npm:7.29.7" dependencies: - "@babel/helper-plugin-utils": ^7.27.1 + "@babel/helper-plugin-utils": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0 - checksum: eb7f4146dc01f1198ce559a90b077e58b951a07521ec414e3c7d4593bf6c4ab5c2af22242a7e9fec085e20299e0ba6ea97f44a45e84ab148141bf9eb959ad25e + checksum: ad06de66ccfb19f0f04e6124d144f3fef72fa5191861b1d04bc32cab87ce43958810d9632eac5881ef991a78b33e68588e3d90e76a63d917bd5a7ff4c96618f8 languageName: node linkType: hard -"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:7.27.1" +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:7.29.7" dependencies: - "@babel/helper-plugin-utils": ^7.27.1 + "@babel/helper-plugin-utils": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0 - checksum: 621cfddfcc99a81e74f8b6f9101fd260b27500cb1a568e3ceae9cc8afe9aee45ac3bca3900a2b66c612b1a2366d29ef67d4df5a1c975be727eaad6906f98c2c6 + checksum: 2189a2a648948107c59ad3bf028e5b71a85b28c840facfead769a33c5f63ae4ec0f147e6a2e664a91a506d4405f5a8972d2ca628f3b64d03edd7620d770761fb languageName: node linkType: hard -"@babel/plugin-bugfix-safari-rest-destructuring-rhs-array@npm:^7.29.3": - version: 7.29.3 - resolution: "@babel/plugin-bugfix-safari-rest-destructuring-rhs-array@npm:7.29.3" +"@babel/plugin-bugfix-safari-rest-destructuring-rhs-array@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-bugfix-safari-rest-destructuring-rhs-array@npm:7.29.7" dependencies: - "@babel/helper-plugin-utils": ^7.28.6 - "@babel/helper-skip-transparent-expression-wrappers": ^7.27.1 + "@babel/helper-plugin-utils": ^7.29.7 + "@babel/helper-skip-transparent-expression-wrappers": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0 - checksum: fd13198afc9b72c6a4e4868f1592fc8010f390e7601148a71d2d6111664c0242d6d5ff27d8eb77ca4c35ef47f8416daf5dbc8d46a498ac706d69c6b3a0988cd7 + checksum: a9bd13c2600bdfcb5b35590e210bcb30f009fda9bd1556567757ea4fcb8ca247750331d6d10774d68127cae4e529bc79abd86a28fe5e2a1cc2cc00e75964ac52 languageName: node linkType: hard -"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@npm:7.27.1" +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@npm:7.29.7" dependencies: - "@babel/helper-plugin-utils": ^7.27.1 - "@babel/helper-skip-transparent-expression-wrappers": ^7.27.1 - "@babel/plugin-transform-optional-chaining": ^7.27.1 + "@babel/helper-plugin-utils": ^7.29.7 + "@babel/helper-skip-transparent-expression-wrappers": ^7.29.7 + "@babel/plugin-transform-optional-chaining": ^7.29.7 peerDependencies: "@babel/core": ^7.13.0 - checksum: f07aa80272bd7a46b7ba11a4644da6c9b6a5a64e848dfaffdad6f02663adefd512e1aaebe664c4dd95f7ed4f80c872c7f8db8d8e34b47aae0930b412a28711a0 + checksum: 76a494ec4f52a127b0208c4574a6da36f6ff5f30484306921762db549fa7d9d9183c837759eb68c0c9e5a56013aa247e6e02e02263384d2a103240353ae0ceb6 languageName: node linkType: hard -"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:7.28.6" +"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:7.29.7" dependencies: - "@babel/helper-plugin-utils": ^7.28.6 - "@babel/traverse": ^7.28.6 + "@babel/helper-plugin-utils": ^7.29.7 + "@babel/traverse": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0 - checksum: f1341f829f809c8685d839669953a478f8a40d1d53f4f5e1972bf39ff4e1ece148319340292d6e0c3641157268b435cbb99b3ac2f3cefe9fca9e81b8f62d6d71 + checksum: 7a58b4b32f4c04b86160dc7900612904e2b88d42c8b89d59a89d3c343f320ad096d73fb453a2e8bf8e97c9d4af3563043bc6d1e3def53c819812cb03f3f873c8 languageName: node linkType: hard @@ -612,14 +688,14 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-import-assertions@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/plugin-syntax-import-assertions@npm:7.28.6" +"@babel/plugin-syntax-import-assertions@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-syntax-import-assertions@npm:7.29.7" dependencies: - "@babel/helper-plugin-utils": ^7.28.6 + "@babel/helper-plugin-utils": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 25017235e1e2c4ed892aa327a3fa10f4209cc618c6dd7806fc40c07d8d7d24a39743d3d5568b8d1c8f416cffe03c174e78874ded513c9338b07a7ab1dcbab050 + checksum: a7f24858e7e833c2ee25779a355b5eff46e4bc93c98b06bda7ea0fd12faf99c4954e0f71074485512045920432790e0269aa562dd4d2085c3f8660ed1cfde8a1 languageName: node linkType: hard @@ -634,14 +710,14 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-import-attributes@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/plugin-syntax-import-attributes@npm:7.28.6" +"@babel/plugin-syntax-import-attributes@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-syntax-import-attributes@npm:7.29.7" dependencies: - "@babel/helper-plugin-utils": ^7.28.6 + "@babel/helper-plugin-utils": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 6c8c6a5988dbb9799d6027360d1a5ba64faabf551f2ef11ba4eade0c62253b5c85d44ddc8eb643c74b9acb2bcaa664a950bd5de9a5d4aef291c4f2a48223bb4b + checksum: 9f47345d09aae16b7ab52ecaf541cde3e3ae1e57e3eb2d4088e062b29dfbd67db55d42d529840557583d66121e2a98788df7a455401cc6d635c8b7700a02efc9 languageName: node linkType: hard @@ -678,6 +754,17 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-syntax-jsx@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-syntax-jsx@npm:7.29.7" + dependencies: + "@babel/helper-plugin-utils": ^7.29.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 84150d27c553a1d3d921354437f6725ca1d63b49514c25591bfcaaafa6ea4d6c10715b66fe7245e4ad7ab7c6cf4b6e1de7373defd3df00877ab12638170d7772 + languageName: node + linkType: hard + "@babel/plugin-syntax-logical-assignment-operators@npm:^7.10.4": version: 7.10.4 resolution: "@babel/plugin-syntax-logical-assignment-operators@npm:7.10.4" @@ -789,737 +876,725 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-arrow-functions@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-arrow-functions@npm:7.27.1" +"@babel/plugin-transform-arrow-functions@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-arrow-functions@npm:7.29.7" dependencies: - "@babel/helper-plugin-utils": ^7.27.1 + "@babel/helper-plugin-utils": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 62c2cc0ae2093336b1aa1376741c5ed245c0987d9e4b4c5313da4a38155509a7098b5acce582b6781cc0699381420010da2e3086353344abe0a6a0ec38961eb7 + checksum: 0037fd7563c7c91cddb8ce104e270bc260190d29c7a297df65e4306471010b4343366de13fab4602cf8ee6c672d3b313b34a01b62f27a333cad16908c83368d8 languageName: node linkType: hard -"@babel/plugin-transform-async-generator-functions@npm:^7.29.0": - version: 7.29.0 - resolution: "@babel/plugin-transform-async-generator-functions@npm:7.29.0" +"@babel/plugin-transform-async-generator-functions@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-async-generator-functions@npm:7.29.7" dependencies: - "@babel/helper-plugin-utils": ^7.28.6 - "@babel/helper-remap-async-to-generator": ^7.27.1 - "@babel/traverse": ^7.29.0 + "@babel/helper-plugin-utils": ^7.29.7 + "@babel/helper-remap-async-to-generator": ^7.29.7 + "@babel/traverse": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: bd549b54283034dd3e2f6c4b41b99a0caba0ddc8e9418490a611136ddb01e62235f14b233fcc172902fd1d18eec6e029245d22212566ea5cb5e24c7450d6005d + checksum: d8239f43b4051b12cd7a5581367bd2b13ac26235da39d79f182999879f010124341ac500f480140b0961a62ec451a0a963b421c509f9c1a306c313f10fc60451 languageName: node linkType: hard -"@babel/plugin-transform-async-to-generator@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/plugin-transform-async-to-generator@npm:7.28.6" +"@babel/plugin-transform-async-to-generator@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-async-to-generator@npm:7.29.7" dependencies: - "@babel/helper-module-imports": ^7.28.6 - "@babel/helper-plugin-utils": ^7.28.6 - "@babel/helper-remap-async-to-generator": ^7.27.1 + "@babel/helper-module-imports": ^7.29.7 + "@babel/helper-plugin-utils": ^7.29.7 + "@babel/helper-remap-async-to-generator": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: bca5774263ec01dd2bf71c74bbaf7baa183bf03576636b7826c3346be70c8c8cb15cff549112f2983c36885131a0afde6c443591278c281f733ee17f455aa9b1 + checksum: e24db9c4c69121daab25883f9a96e6849fa664c78c6bbcfb77fe0a0c6ab29b81ba39e8497985367463d3a88deac3b5bbe15dd1c5d0e5dd492cfccf8efdd27452 languageName: node linkType: hard -"@babel/plugin-transform-block-scoped-functions@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-block-scoped-functions@npm:7.27.1" +"@babel/plugin-transform-block-scoped-functions@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-block-scoped-functions@npm:7.29.7" dependencies: - "@babel/helper-plugin-utils": ^7.27.1 + "@babel/helper-plugin-utils": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 7fb4988ca80cf1fc8345310d5edfe38e86b3a72a302675cdd09404d5064fe1d1fe1283ebe658ad2b71445ecef857bfb29a748064306b5f6c628e0084759c2201 + checksum: 24f9712ade98061cd22088709b86b8e3e19ea416dbe5a69ad504fc3f8f2179af5bdeb32fcb9c24fc861bef515e41ae5ef72cd909e0e42bb0cf15838c4e737149 languageName: node linkType: hard -"@babel/plugin-transform-block-scoping@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/plugin-transform-block-scoping@npm:7.28.6" +"@babel/plugin-transform-block-scoping@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-block-scoping@npm:7.29.7" dependencies: - "@babel/helper-plugin-utils": ^7.28.6 + "@babel/helper-plugin-utils": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: cb4f71ac4fc7b32c2e3cc167eb9e7a1a11562127d702e3b5093567750e9a4eb11a29ae5a917f62741bf9d5792bfe3022cbcdcc7bb927ddb6f627b6749a38c118 + checksum: a17c02f8dfcaf2c26c0c323aaa8e3a1616f2de3ea0a4947e16789bb64cb0f177deff388eb1390c100c82d7e6fecd4d583646bb9305fb3df3ca824b1bdbebdc8e languageName: node linkType: hard -"@babel/plugin-transform-class-properties@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/plugin-transform-class-properties@npm:7.28.6" +"@babel/plugin-transform-class-properties@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-class-properties@npm:7.29.7" dependencies: - "@babel/helper-create-class-features-plugin": ^7.28.6 - "@babel/helper-plugin-utils": ^7.28.6 + "@babel/helper-create-class-features-plugin": ^7.29.7 + "@babel/helper-plugin-utils": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 200f30d44b36a768fa3a8cf690db9e333996af2ad14d9fa1b4c91a427ed9302907873b219b4ce87517ca1014a810eb2e929a6a66be68473f72b546fc64d04fbc + checksum: 0cc5e7a882e29eead360f02ef79f6b2ec3b3813213b1513d8fdaa931d1d1361fccc92fbacc9b399e42495953d9d6fc722f283b5f3aa272fe016a0b5fe1e6a130 languageName: node linkType: hard -"@babel/plugin-transform-class-static-block@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/plugin-transform-class-static-block@npm:7.28.6" +"@babel/plugin-transform-class-static-block@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-class-static-block@npm:7.29.7" dependencies: - "@babel/helper-create-class-features-plugin": ^7.28.6 - "@babel/helper-plugin-utils": ^7.28.6 + "@babel/helper-create-class-features-plugin": ^7.29.7 + "@babel/helper-plugin-utils": ^7.29.7 peerDependencies: "@babel/core": ^7.12.0 - checksum: 3db326156f73a0c0d1e2ea4d73e082b9ace2f6a9c965db1c2e51f3a186751b8b91bafb184d05e046bf970b50ecfde1f74862dd895f9a5ea0fad328369d74cfc4 + checksum: fe94eb94d8417de753a26f06a3c50780cdfc3f07e10bcd09dde2fe61dcd9a2714b83b1b2d36733328a3ad09b02e84fa06197f757644ffbcca1673e87c64ecb76 languageName: node linkType: hard -"@babel/plugin-transform-classes@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/plugin-transform-classes@npm:7.28.6" +"@babel/plugin-transform-classes@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-classes@npm:7.29.7" dependencies: - "@babel/helper-annotate-as-pure": ^7.27.3 - "@babel/helper-compilation-targets": ^7.28.6 - "@babel/helper-globals": ^7.28.0 - "@babel/helper-plugin-utils": ^7.28.6 - "@babel/helper-replace-supers": ^7.28.6 - "@babel/traverse": ^7.28.6 + "@babel/helper-annotate-as-pure": ^7.29.7 + "@babel/helper-compilation-targets": ^7.29.7 + "@babel/helper-globals": ^7.29.7 + "@babel/helper-plugin-utils": ^7.29.7 + "@babel/helper-replace-supers": ^7.29.7 + "@babel/traverse": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: bddeefbfd1966272e5da6a0844d68369a0f43c286816c8b379dfd576cf835b8bc652089ef337b0334ff3ae6c9652d56d8332b78a7d29176534265c39856e4822 + checksum: cc45ff5b5b063339131cd701266af90506db8640e56494de0c78f882da6317f057951bf6507c5b48a0278cf5dad21691baf2af05e24b8c26b0725d677088edbf languageName: node linkType: hard -"@babel/plugin-transform-computed-properties@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/plugin-transform-computed-properties@npm:7.28.6" +"@babel/plugin-transform-computed-properties@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-computed-properties@npm:7.29.7" dependencies: - "@babel/helper-plugin-utils": ^7.28.6 - "@babel/template": ^7.28.6 + "@babel/helper-plugin-utils": ^7.29.7 + "@babel/template": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: fd1fcc55003a2584c7461bf214ae9e9fce370ad09339319e99e29e5e55a8a3bd485d10805b3d69636a738208761b3a5b0dafdd023534396be45a36409082b014 + checksum: ad945a48e6826c3b34f825e780ab33bf91e18c7924dd263e44bef8d8a6350636305b22af8f00793d3767482004651f4bfb9fed0c92f05c01b99ae80d79956e67 languageName: node linkType: hard -"@babel/plugin-transform-destructuring@npm:^7.28.5": - version: 7.28.5 - resolution: "@babel/plugin-transform-destructuring@npm:7.28.5" +"@babel/plugin-transform-destructuring@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-destructuring@npm:7.29.7" dependencies: - "@babel/helper-plugin-utils": ^7.27.1 - "@babel/traverse": ^7.28.5 + "@babel/helper-plugin-utils": ^7.29.7 + "@babel/traverse": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 74a06e55e715cfda0fdd8be53d2655d64dfdc28dffaede329d42548fd5b1449ad26a4ce43a24c3fd277b96f8b2010c7b3915afa8297911cda740cc5cc3a81f38 + checksum: 5f56c030beec2ae1640909eb5213fc655f0062046b28699d049cc8b00fb7d9aa1c5ba1dc1c7ee41c8bae97be778066f1f9ea2ecd8fff872a1e8f10fd3addf18c languageName: node linkType: hard -"@babel/plugin-transform-dotall-regex@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/plugin-transform-dotall-regex@npm:7.28.6" +"@babel/plugin-transform-dotall-regex@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-dotall-regex@npm:7.29.7" dependencies: - "@babel/helper-create-regexp-features-plugin": ^7.28.5 - "@babel/helper-plugin-utils": ^7.28.6 + "@babel/helper-create-regexp-features-plugin": ^7.29.7 + "@babel/helper-plugin-utils": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 866ffbbdee77fa955063b37c75593db8dbbe46b1ebb64cc788ea437e3a9aa41cb7b9afcee617c678a32b6705baa0892ec8e5d4b8af3bbb0ab1b254514ccdbd37 + checksum: 537df0fb915a420df715a2f4da16ab6c08ce2370521edef9a8a59af23a533314109f6abd836c5e127c8cea4a46bc4a05692670cf7ad64868c286075fa2d7848c languageName: node linkType: hard -"@babel/plugin-transform-duplicate-keys@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-duplicate-keys@npm:7.27.1" +"@babel/plugin-transform-duplicate-keys@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-duplicate-keys@npm:7.29.7" dependencies: - "@babel/helper-plugin-utils": ^7.27.1 + "@babel/helper-plugin-utils": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: ef2112d658338e3ff0827f39a53c0cfa211f1cbbe60363bca833a5269df389598ec965e7283600b46533c39cdca82307d0d69c0f518290ec5b00bb713044715b + checksum: 39bf312a798792e361d2afa9e900eb7d7fd853239a776912bafc5bb3799886374d54a0882d21517296086abdd3e5458405f6f3a7da5dcb493bc86c5a32576bab languageName: node linkType: hard -"@babel/plugin-transform-duplicate-named-capturing-groups-regex@npm:^7.29.0": - version: 7.29.0 - resolution: "@babel/plugin-transform-duplicate-named-capturing-groups-regex@npm:7.29.0" +"@babel/plugin-transform-duplicate-named-capturing-groups-regex@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-duplicate-named-capturing-groups-regex@npm:7.29.7" dependencies: - "@babel/helper-create-regexp-features-plugin": ^7.28.5 - "@babel/helper-plugin-utils": ^7.28.6 + "@babel/helper-create-regexp-features-plugin": ^7.29.7 + "@babel/helper-plugin-utils": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0 - checksum: 7fa7b773259a578c9e01c80946f75ecc074520064aa7a87a65db06c7df70766e2fa6be78cda55fa9418a14e30b2b9d595484a46db48074d495d9f877a4276065 + checksum: fa7fcdbede10dbc06fe4f861e90286f7f599d3f3c43e69445e63c3f48422fd34db0b0dd9bbebccd1dbd04a50fca4ab22fd82d28e7bc8fe9b6d5790c9e694d380 languageName: node linkType: hard -"@babel/plugin-transform-dynamic-import@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-dynamic-import@npm:7.27.1" +"@babel/plugin-transform-dynamic-import@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-dynamic-import@npm:7.29.7" dependencies: - "@babel/helper-plugin-utils": ^7.27.1 + "@babel/helper-plugin-utils": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 7a9fbc8d17148b7f11a1d1ca3990d2c2cd44bd08a45dcaf14f20a017721235b9044b20e6168b6940282bb1b48fb78e6afbdfb9dd9d82fde614e15baa7d579932 + checksum: 58c035e6b9103c225f3d181671d9b3dec140351c3ecf12bc3a66b8653be41161f20135ada00a703244c2bfc9dd57b62fc54f77f2f6fe43df6c598358f377e6fa languageName: node linkType: hard -"@babel/plugin-transform-explicit-resource-management@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/plugin-transform-explicit-resource-management@npm:7.28.6" +"@babel/plugin-transform-explicit-resource-management@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-explicit-resource-management@npm:7.29.7" dependencies: - "@babel/helper-plugin-utils": ^7.28.6 - "@babel/plugin-transform-destructuring": ^7.28.5 + "@babel/helper-plugin-utils": ^7.29.7 + "@babel/plugin-transform-destructuring": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: be65403694d360793b1b626ac0dfa7c120cfe4dd1c95a81a30b6e7426dc317643e60a486d642e318a4d3d9a7193e72fdb36e2ec140c25c773dcb9c3b1e2854ef + checksum: 28ff30f46d97b91ba5f57ae63499a489fa1ec3dcc427ec851c2aacb34106b573c58eba4be000bc4c28223ba767cfadc008cdfa9f833ed12996e2f014e0a06373 languageName: node linkType: hard -"@babel/plugin-transform-exponentiation-operator@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/plugin-transform-exponentiation-operator@npm:7.28.6" +"@babel/plugin-transform-exponentiation-operator@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-exponentiation-operator@npm:7.29.7" dependencies: - "@babel/helper-plugin-utils": ^7.28.6 + "@babel/helper-plugin-utils": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: b232152499370435c7cd4bf3321f58e189150e35ca3722ea16533d33434b97294df1342f5499671ec48e62b71c34cdea0ca8cf317ad12594a10f6fc670315e62 + checksum: bf0366d77d318d4b6eae6880217e3fdfcb6e5f7913f658583de9537fd4fca1f05f9ac4083d8f946a84eaefec068cbba948be90f4a39484c85bc69082def3162d languageName: node linkType: hard -"@babel/plugin-transform-export-namespace-from@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-export-namespace-from@npm:7.27.1" +"@babel/plugin-transform-export-namespace-from@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-export-namespace-from@npm:7.29.7" dependencies: - "@babel/helper-plugin-utils": ^7.27.1 + "@babel/helper-plugin-utils": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 85082923eca317094f08f4953d8ea2a6558b3117826c0b740676983902b7236df1f4213ad844cb38c2dae104753dbe8f1cc51f01567835d476d32f5f544a4385 + checksum: d157d62b144d1626b801e557dcede914db33e78f3f4230f487e5709c21efd40648f7f3a47a44a7fce694ad9cd117d2ac3ed796da0102275fd02b4fdb317d906b languageName: node linkType: hard -"@babel/plugin-transform-for-of@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-for-of@npm:7.27.1" +"@babel/plugin-transform-for-of@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-for-of@npm:7.29.7" dependencies: - "@babel/helper-plugin-utils": ^7.27.1 - "@babel/helper-skip-transparent-expression-wrappers": ^7.27.1 + "@babel/helper-plugin-utils": ^7.29.7 + "@babel/helper-skip-transparent-expression-wrappers": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: c9224e08de5d80b2c834383d4359aa9e519db434291711434dd996a4f86b7b664ad67b45d65459b7ec11fa582e3e11a3c769b8a8ca71594bdd4e2f0503f84126 + checksum: 7641d5eb4ef268df2f7d8736691a565646f42c55fdc2c86a65ed027276415a19ac6cafab2fc386621894c5d3202baacc9f222424bda37fa2ab9a20d7fec921f9 languageName: node linkType: hard -"@babel/plugin-transform-function-name@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-function-name@npm:7.27.1" +"@babel/plugin-transform-function-name@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-function-name@npm:7.29.7" dependencies: - "@babel/helper-compilation-targets": ^7.27.1 - "@babel/helper-plugin-utils": ^7.27.1 - "@babel/traverse": ^7.27.1 + "@babel/helper-compilation-targets": ^7.29.7 + "@babel/helper-plugin-utils": ^7.29.7 + "@babel/traverse": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 26a2a183c3c52a96495967420a64afc5a09f743a230272a131668abf23001e393afa6371e6f8e6c60f4182bea210ed31d1caf866452d91009c1daac345a52f23 + checksum: 87a6329442ef8085fbc160e659f64562f0f5b63be65403b8bbb8e18c67dd7d03b82fb2e1371fdde734e2f05b13a72f88ed8d8cb03807150063954b9604d082cf languageName: node linkType: hard -"@babel/plugin-transform-json-strings@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/plugin-transform-json-strings@npm:7.28.6" +"@babel/plugin-transform-json-strings@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-json-strings@npm:7.29.7" dependencies: - "@babel/helper-plugin-utils": ^7.28.6 + "@babel/helper-plugin-utils": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 69d82a1a0a72ed6e6f7969e09cf330516599d79b2b4e680e9dd3c57616a8c6af049b5103456e370ab56642815e80e46ed88bb81e9e059304a85c5fe0bf137c29 + checksum: 3af97e144e0d986522f01803ffa0f90741530d1610952ac6a92511c356ecbf5616092ab1d21401d25bc7cb8ac90d73c2c7ff35e41766df2708c29d7e588cfa7f languageName: node linkType: hard -"@babel/plugin-transform-literals@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-literals@npm:7.27.1" +"@babel/plugin-transform-literals@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-literals@npm:7.29.7" dependencies: - "@babel/helper-plugin-utils": ^7.27.1 + "@babel/helper-plugin-utils": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 0a76d12ab19f32dd139964aea7da48cecdb7de0b75e207e576f0f700121fe92367d788f328bf4fb44b8261a0f605c97b44e62ae61cddbb67b14e94c88b411f95 + checksum: aadb2b3fe85186c274a07d5486aeef9496ce374e534fbc7b54f77985c75513422d9acec4c532f67b027e939644d93a69c00505b8909e259184c3ee5c5c62c46b languageName: node linkType: hard -"@babel/plugin-transform-logical-assignment-operators@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/plugin-transform-logical-assignment-operators@npm:7.28.6" +"@babel/plugin-transform-logical-assignment-operators@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-logical-assignment-operators@npm:7.29.7" dependencies: - "@babel/helper-plugin-utils": ^7.28.6 + "@babel/helper-plugin-utils": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 36095d5d1cfc680e95298b5389a16016da800ae3379b130dabf557e94652c47b06610407e9fa44aaa03e9b0a5aa7b4b93348123985d44a45e369bf5f3497d149 + checksum: 374d83dfbb2de5e339d2966487c0f0d766cd67422addbd0172104ff2788b60317858172a7ab2cb6ee7d5bffad72ce07120fec009a2ef3b35551013fce4908686 languageName: node linkType: hard -"@babel/plugin-transform-member-expression-literals@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-member-expression-literals@npm:7.27.1" +"@babel/plugin-transform-member-expression-literals@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-member-expression-literals@npm:7.29.7" dependencies: - "@babel/helper-plugin-utils": ^7.27.1 + "@babel/helper-plugin-utils": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 804121430a6dcd431e6ffe99c6d1fbbc44b43478113b79c677629e7f877b4f78a06b69c6bfb2747fd84ee91879fe2eb32e4620b53124603086cf5b727593ebe8 + checksum: 698cbc9500e8caea1d36b48248112d60e023cea9d0772ac1ecf1639b38b662d9352043747dbe617fe1f6f17709bc17601534f7bf2f22c791fb86f7e2ab43e39f languageName: node linkType: hard -"@babel/plugin-transform-modules-amd@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-modules-amd@npm:7.27.1" +"@babel/plugin-transform-modules-amd@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-modules-amd@npm:7.29.7" dependencies: - "@babel/helper-module-transforms": ^7.27.1 - "@babel/helper-plugin-utils": ^7.27.1 + "@babel/helper-module-transforms": ^7.29.7 + "@babel/helper-plugin-utils": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 8bb36d448e438d5d30f4faf19120e8c18aa87730269e65d805bf6032824d175ed738057cc392c2c8a650028f1ae0f346cad8d6b723f31a037b586e2092a7be18 + checksum: 6fce7d329230e3be0389b1135b6ffa1224c3f060294409137c5bb7f26d81ac47b6d91651deaef93b17f5e6f99e5ca7edb80b6b855b562b65ad00b3d7f717da40 languageName: node linkType: hard -"@babel/plugin-transform-modules-commonjs@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/plugin-transform-modules-commonjs@npm:7.28.6" +"@babel/plugin-transform-modules-commonjs@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-modules-commonjs@npm:7.29.7" dependencies: - "@babel/helper-module-transforms": ^7.28.6 - "@babel/helper-plugin-utils": ^7.28.6 + "@babel/helper-module-transforms": ^7.29.7 + "@babel/helper-plugin-utils": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: b48cab26fda72894c7002a9c783befbc8a643d827c52bdcc5adf83e418ca93224a15aaf7ed2d1e6284627be55913696cfa2119242686cfa77a473bf79314df26 + checksum: e9d8102deca4c2f06507a8d071ca0e161f01cec0e108151142edb39995bd830e312d55d21fac0ceb390ac79a1fee5fb768b719413b8fc5adda5f06ecd8845cd6 languageName: node linkType: hard -"@babel/plugin-transform-modules-systemjs@npm:^7.29.0": - version: 7.29.4 - resolution: "@babel/plugin-transform-modules-systemjs@npm:7.29.4" +"@babel/plugin-transform-modules-systemjs@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-modules-systemjs@npm:7.29.7" dependencies: - "@babel/helper-module-transforms": ^7.28.6 - "@babel/helper-plugin-utils": ^7.28.6 - "@babel/helper-validator-identifier": ^7.28.5 - "@babel/traverse": ^7.29.0 + "@babel/helper-module-transforms": ^7.29.7 + "@babel/helper-plugin-utils": ^7.29.7 + "@babel/helper-validator-identifier": ^7.29.7 + "@babel/traverse": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: d9cbb30669077756048af990a08ad1ba149785c336024affa49848dc4ffc5948bfaaf52d90bbec711a1f320e19e2c60182dbeff40d81cc5b9a09a87919abe07d + checksum: 185d26d1f20fabdb120cb0bacdb2d245a8fbe628778cc2cd096a804c1169e21ae555e482b76fcc04a585edd70d9758a456794ae4d69cd41e638e10f620d65058 languageName: node linkType: hard -"@babel/plugin-transform-modules-umd@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-modules-umd@npm:7.27.1" +"@babel/plugin-transform-modules-umd@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-modules-umd@npm:7.29.7" dependencies: - "@babel/helper-module-transforms": ^7.27.1 - "@babel/helper-plugin-utils": ^7.27.1 + "@babel/helper-module-transforms": ^7.29.7 + "@babel/helper-plugin-utils": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: b007dd89231f2eeccf1c71a85629bcb692573303977a4b1c5f19a835ea6b5142c18ef07849bc6d752b874a11bc0ddf3c67468b77c8ee8310290b688a4f01ef31 + checksum: 589f5c30a906587d039e2f3bf8267652be272d93d3056667b479f450318c91e55d1674631239ac25e0e9591f4abb7ff225bb0fc8af58e5bfb703d3385ec02082 languageName: node linkType: hard -"@babel/plugin-transform-named-capturing-groups-regex@npm:^7.29.0": - version: 7.29.0 - resolution: "@babel/plugin-transform-named-capturing-groups-regex@npm:7.29.0" +"@babel/plugin-transform-named-capturing-groups-regex@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-named-capturing-groups-regex@npm:7.29.7" dependencies: - "@babel/helper-create-regexp-features-plugin": ^7.28.5 - "@babel/helper-plugin-utils": ^7.28.6 + "@babel/helper-create-regexp-features-plugin": ^7.29.7 + "@babel/helper-plugin-utils": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0 - checksum: ed8c27699ca82a6c01cbfd39f3de16b90cfea4f8146a358057f76df290d308a66a8bd2e6734e6a87f68c18576e15d2d70548a84cd474d26fdf256c3f5ae44d8c + checksum: 3a481be133e9ca5d25570b5ed62daae323a51663bacf30fed0d1980e912047ebd34d6326533182db625fc0bbd086d1a23ed68ebb6108e7a68a8650c228afc084 languageName: node linkType: hard -"@babel/plugin-transform-new-target@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-new-target@npm:7.27.1" +"@babel/plugin-transform-new-target@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-new-target@npm:7.29.7" dependencies: - "@babel/helper-plugin-utils": ^7.27.1 + "@babel/helper-plugin-utils": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 32c8078d843bda001244509442d68fd3af088d7348ba883f45c262b2c817a27ffc553b0d78e7f7a763271b2ece7fac56151baad7a91fb21f5bb1d2f38e5acad7 + checksum: 35b4c295348d17c9c00cf772663a6e705fd48f5a9a5378d7b548ab4cb71d5f183ca9446d2a86c77f16b037cfe64c621c00e93219aefab43bfd39d8dd2c8b56bb languageName: node linkType: hard -"@babel/plugin-transform-nullish-coalescing-operator@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/plugin-transform-nullish-coalescing-operator@npm:7.28.6" +"@babel/plugin-transform-nullish-coalescing-operator@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-nullish-coalescing-operator@npm:7.29.7" dependencies: - "@babel/helper-plugin-utils": ^7.28.6 + "@babel/helper-plugin-utils": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 1cdd3ca48a8fffa13dbb9949748d3dd2183cf24110cd55d702da4549205611fc12978b49886be809ec1929ff6304ac4eecc747a33dca2484f9dc655928ab5a89 + checksum: f486e737ddcec3a88e2e0dc004c28e15156dd255f3b2d944903f3d75666257c96ee7ebf57d80d2cf42eda2bee497db8134a26d657ddc3defcc34b9583ecbd119 languageName: node linkType: hard -"@babel/plugin-transform-numeric-separator@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/plugin-transform-numeric-separator@npm:7.28.6" +"@babel/plugin-transform-numeric-separator@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-numeric-separator@npm:7.29.7" dependencies: - "@babel/helper-plugin-utils": ^7.28.6 + "@babel/helper-plugin-utils": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 4b5ca60e481e22f0842761a3badca17376a230b5a7e5482338604eb95836c2d0c9c9bde53bdc5c2de1c6a12ae6c12de7464d098bf74b0943f85905ca358f0b68 + checksum: 6177df9e1a8a190bf4a360f8cbcfa614b70ededba61201bd0a38929770b6d00a8a54a19f8fda82cf60688d9bab938427a9fe5dae0a9e8cd8ed79c88a3b2dbcd7 languageName: node linkType: hard -"@babel/plugin-transform-object-rest-spread@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/plugin-transform-object-rest-spread@npm:7.28.6" +"@babel/plugin-transform-object-rest-spread@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-object-rest-spread@npm:7.29.7" dependencies: - "@babel/helper-compilation-targets": ^7.28.6 - "@babel/helper-plugin-utils": ^7.28.6 - "@babel/plugin-transform-destructuring": ^7.28.5 - "@babel/plugin-transform-parameters": ^7.27.7 - "@babel/traverse": ^7.28.6 + "@babel/helper-compilation-targets": ^7.29.7 + "@babel/helper-plugin-utils": ^7.29.7 + "@babel/plugin-transform-destructuring": ^7.29.7 + "@babel/plugin-transform-parameters": ^7.29.7 + "@babel/traverse": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: ab85b1321f86db91aba22ad9d8e6ab65448c983214998012229f5302468527d27b908ad6b14755991c317e35d2f54ec8459a2a094a755999651fe0ac9bd2e9a6 + checksum: e09bcc8800cf374962ab98bce5ccceb900266278a3a1e4a68391abec440fdf7371c8059f9091f407a1b167f3acf624c34c9b92188674fdcb7797e3f02509216b languageName: node linkType: hard -"@babel/plugin-transform-object-super@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-object-super@npm:7.27.1" +"@babel/plugin-transform-object-super@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-object-super@npm:7.29.7" dependencies: - "@babel/helper-plugin-utils": ^7.27.1 - "@babel/helper-replace-supers": ^7.27.1 - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 46b819cb9a6cd3cfefe42d07875fee414f18d5e66040366ae856116db560ad4e16f3899a0a7fddd6773e0d1458444f94b208b67c0e3b6977a27ea17a5c13dbf6 - languageName: node - linkType: hard - -"@babel/plugin-transform-optional-catch-binding@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/plugin-transform-optional-catch-binding@npm:7.28.6" - dependencies: - "@babel/helper-plugin-utils": ^7.28.6 + "@babel/helper-plugin-utils": ^7.29.7 + "@babel/helper-replace-supers": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: ee24a17defec056eb9ef01824d7e4a1f65d531af6b4b79acfd0bcb95ce0b47926e80c61897f36f8c01ce733b069c9acdb1c9ce5ec07a729d0dbf9e8d859fe992 + checksum: 65ed8719563572c4917f19b32c476c9a9062fccf89bfd44a418bb734cd866034d66049499cace58e2bb4589da779983f534078bd989333f36268b9da08d4b33c languageName: node linkType: hard -"@babel/plugin-transform-optional-chaining@npm:^7.27.1": - version: 7.28.5 - resolution: "@babel/plugin-transform-optional-chaining@npm:7.28.5" +"@babel/plugin-transform-optional-catch-binding@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-optional-catch-binding@npm:7.29.7" dependencies: - "@babel/helper-plugin-utils": ^7.27.1 - "@babel/helper-skip-transparent-expression-wrappers": ^7.27.1 + "@babel/helper-plugin-utils": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 78c2be52b32e893c992aca52ef84130b3540e2ca0e1ff0e45f8d2ccc213b3c6e2b43f8dd2c86a0976acf3cdff97d4488c23b86d7a3e67daa517013089f44af1d + checksum: 4b6e41e1dc5dbd02cfe0b96214130cca5fd3bd879551fc82188bb3d9a2782af9bab50f2140af9ff946a8ee23b9478ee42810641fb99aa3e033884d7c6103d138 languageName: node linkType: hard -"@babel/plugin-transform-optional-chaining@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/plugin-transform-optional-chaining@npm:7.28.6" +"@babel/plugin-transform-optional-chaining@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-optional-chaining@npm:7.29.7" dependencies: - "@babel/helper-plugin-utils": ^7.28.6 - "@babel/helper-skip-transparent-expression-wrappers": ^7.27.1 + "@babel/helper-plugin-utils": ^7.29.7 + "@babel/helper-skip-transparent-expression-wrappers": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: a40dbe709671a436bb69e14524805e10af81b44c422e4fc5dc905cb91adb92d650c9d266c3c2c0da0d410dea89ce784995d4118b7ab6a7544f4923e61590b386 + checksum: 6255d259bb0143f7938278ebb382aba22311c260919d3f08476509c76335a111b479b3ad7363e86de064f87af85ca4d7f03f08195f0646c525ea70fb587c0a2d languageName: node linkType: hard -"@babel/plugin-transform-parameters@npm:^7.27.7": - version: 7.27.7 - resolution: "@babel/plugin-transform-parameters@npm:7.27.7" +"@babel/plugin-transform-parameters@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-parameters@npm:7.29.7" dependencies: - "@babel/helper-plugin-utils": ^7.27.1 + "@babel/helper-plugin-utils": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: d51f195e1d6ac5d9fce583e9a70a5bfe403e62386e5eb06db9fbc6533f895a98ff7e7c3dcaa311a8e6fa7a9794466e81cdabcba6af9f59d787fb767bfe7868b4 + checksum: 615cdd72dc2d08051e6d4e7f0539661e40029257a047ce15c5da5f4394a372a53f6f6d6aece72ad15ccf0590e448c9a742f8576564321c9dcc16262ec6197c9b languageName: node linkType: hard -"@babel/plugin-transform-private-methods@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/plugin-transform-private-methods@npm:7.28.6" +"@babel/plugin-transform-private-methods@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-private-methods@npm:7.29.7" dependencies: - "@babel/helper-create-class-features-plugin": ^7.28.6 - "@babel/helper-plugin-utils": ^7.28.6 + "@babel/helper-create-class-features-plugin": ^7.29.7 + "@babel/helper-plugin-utils": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: b80179b28f6a165674d0b0d6c6349b13a01dd282b18f56933423c0a33c23fc0626c8f011f859fc20737d021fe966eb8474a5233e4596401482e9ee7fb00e2aa2 + checksum: 5055af2b86a95acbf6bd1a14256edf439ba4f214707f6aa9f6a29d1168c882e5709853c4ff225f55575f88d3a58effbed952d25c5cd70f93785106541f992cdd languageName: node linkType: hard -"@babel/plugin-transform-private-property-in-object@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/plugin-transform-private-property-in-object@npm:7.28.6" +"@babel/plugin-transform-private-property-in-object@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-private-property-in-object@npm:7.29.7" dependencies: - "@babel/helper-annotate-as-pure": ^7.27.3 - "@babel/helper-create-class-features-plugin": ^7.28.6 - "@babel/helper-plugin-utils": ^7.28.6 + "@babel/helper-annotate-as-pure": ^7.29.7 + "@babel/helper-create-class-features-plugin": ^7.29.7 + "@babel/helper-plugin-utils": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 32a935e44872e90607851be5bc2cd3365f29c0e0e3853ef3e2b6a7da4d08c647379bf2f2dc4f14a9064d7d72e2cf75da85e55baeeec1ffc25cf6088fe24422f7 + checksum: 068ff9e35e103b269c707d16f50384646295a6613c5abfdebea24f0430bb18ea4ef40a299e1dcc915bb22f65e2217c3428c20bcd4a3fe5f8ac60ec212835646d languageName: node linkType: hard -"@babel/plugin-transform-property-literals@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-property-literals@npm:7.27.1" +"@babel/plugin-transform-property-literals@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-property-literals@npm:7.29.7" dependencies: - "@babel/helper-plugin-utils": ^7.27.1 + "@babel/helper-plugin-utils": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 7caec27d5ed8870895c9faf4f71def72745d69da0d8e77903146a4e135fd7bed5778f5f9cebb36c5fba86338e6194dd67a08c033fc84b4299b7eceab6d9630cb + checksum: 7e7a557df8feb50cd6913158c6d12df0e8a9da58e3f73e7cbfc08af399055b03e77a22b12c73d5bf6bb49239617d6189ccb6021ab03f0225bc54f9c74a880b62 languageName: node linkType: hard -"@babel/plugin-transform-react-display-name@npm:^7.28.0": - version: 7.28.0 - resolution: "@babel/plugin-transform-react-display-name@npm:7.28.0" +"@babel/plugin-transform-react-display-name@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-react-display-name@npm:7.29.7" dependencies: - "@babel/helper-plugin-utils": ^7.27.1 + "@babel/helper-plugin-utils": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 268b1a9192974439d17949e170b01cac2a2aa003c844e2fe3b8361146f42f66487178cffdfa8ce862aa9e6c814bc37f879a70300cb3f067815d15fa6aad04e6d + checksum: ded95cce1816f800db43e8f4e1f7fbb928091bf036438617b8ca7e9ce776079606045a0ca482904bfeff801c4fc726de633153843c441ef31980b8c41ace04c9 languageName: node linkType: hard -"@babel/plugin-transform-react-jsx-development@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-react-jsx-development@npm:7.27.1" +"@babel/plugin-transform-react-jsx-development@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-react-jsx-development@npm:7.29.7" dependencies: - "@babel/plugin-transform-react-jsx": ^7.27.1 + "@babel/plugin-transform-react-jsx": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: b88865d5b8c018992f2332da939faa15c4d4a864c9435a5937beaff3fe43781432cc42e0a5d5631098e0bd4066fc33f5fa72203b388b074c3545fe7aaa21e474 + checksum: c535bb5ee09e07839a422f7a8e55849cd30525af57021888eceb84d33391290f6250207319bb4fbb4d4cbdcdb894b2a2b963f0769a3e95536370159b4b505855 languageName: node linkType: hard -"@babel/plugin-transform-react-jsx@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-react-jsx@npm:7.27.1" +"@babel/plugin-transform-react-jsx@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-react-jsx@npm:7.29.7" dependencies: - "@babel/helper-annotate-as-pure": ^7.27.1 - "@babel/helper-module-imports": ^7.27.1 - "@babel/helper-plugin-utils": ^7.27.1 - "@babel/plugin-syntax-jsx": ^7.27.1 - "@babel/types": ^7.27.1 + "@babel/helper-annotate-as-pure": ^7.29.7 + "@babel/helper-module-imports": ^7.29.7 + "@babel/helper-plugin-utils": ^7.29.7 + "@babel/plugin-syntax-jsx": ^7.29.7 + "@babel/types": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 960d36e5d11ba68e4fbf1e2b935c153cb6ea7b0004f838aaee8baf7de30462b8f0562743a39ce3c370cc70b8f79d3c549104a415a615b2b0055b71fd025df0f3 + checksum: d50e5d6f12051c688280b118fc0cdc49f617f7c1f2c41b25733b606aa9a14d2dc84bc544163d115226b9d2cde9f147f49568350b9d100cb47988e5e76cf495c7 languageName: node linkType: hard -"@babel/plugin-transform-react-pure-annotations@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-react-pure-annotations@npm:7.27.1" +"@babel/plugin-transform-react-pure-annotations@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-react-pure-annotations@npm:7.29.7" dependencies: - "@babel/helper-annotate-as-pure": ^7.27.1 - "@babel/helper-plugin-utils": ^7.27.1 + "@babel/helper-annotate-as-pure": ^7.29.7 + "@babel/helper-plugin-utils": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: a6f591c5e85a1ab0685d4a25afe591fe8d11dc0b73c677cf9560ff8d540d036a1cce9efcb729fc9092def4d854dc304ffdc063a89a9247900b69c516bf971a4c + checksum: 7b6bc9e9db06f2c40685b4f0a043af17a98a8bee833831aa28f70c89876dc649fdd682ae572445143b53fe091258964107bae9d3583480eb1c4f1d9c22780b38 languageName: node linkType: hard -"@babel/plugin-transform-regenerator@npm:^7.29.0": - version: 7.29.0 - resolution: "@babel/plugin-transform-regenerator@npm:7.29.0" +"@babel/plugin-transform-regenerator@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-regenerator@npm:7.29.7" dependencies: - "@babel/helper-plugin-utils": ^7.28.6 + "@babel/helper-plugin-utils": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: f48bc814f11239f2bfe010a6e29d5ac2443e7b1d8004e7c022effa111b743491127acf8644cfef475edb86b91f123829585867bc13762652aabd9b85ed6ce61e + checksum: 1a136712ba92693402d7fafb96624d1a833e888cd59029a84ed24d8ff083304a3f1d101d8d5013d0400229041c8a1e4ddf08027268f3c876ea226e86734acd25 languageName: node linkType: hard -"@babel/plugin-transform-regexp-modifiers@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/plugin-transform-regexp-modifiers@npm:7.28.6" +"@babel/plugin-transform-regexp-modifiers@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-regexp-modifiers@npm:7.29.7" dependencies: - "@babel/helper-create-regexp-features-plugin": ^7.28.5 - "@babel/helper-plugin-utils": ^7.28.6 + "@babel/helper-create-regexp-features-plugin": ^7.29.7 + "@babel/helper-plugin-utils": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0 - checksum: 5aacc570034c085afa0165137bb9a04cd4299b86eb9092933a96dcc1132c8f591d9d534419988f5f762b2f70d43a3c719a6b8fa05fdd3b2b1820d01cf85500da + checksum: bfbc6b898ace99b8412eb6e902b90856188c692e69672d42d48c5e22a5bf9b0d15d35424fda8501bfb06ba0504acc5f1b9e13eacaba232aa58af74472d6068dc languageName: node linkType: hard -"@babel/plugin-transform-reserved-words@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-reserved-words@npm:7.27.1" +"@babel/plugin-transform-reserved-words@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-reserved-words@npm:7.29.7" dependencies: - "@babel/helper-plugin-utils": ^7.27.1 + "@babel/helper-plugin-utils": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: dea0b66742d2863b369c06c053e11e15ba785892ea19cccf7aef3c1bdaa38b6ab082e19984c5ea7810d275d9445c5400fcc385ad71ce707ed9256fadb102af3b + checksum: ffd7f86ddce36c6ded2dd9218f81be8cbae35b1ed01100ac0a98623bd0a76c059188b70953ab5accae8f8430451e8ed4779d533ac5e35c523f5004a981208b7c languageName: node linkType: hard -"@babel/plugin-transform-shorthand-properties@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-shorthand-properties@npm:7.27.1" +"@babel/plugin-transform-shorthand-properties@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-shorthand-properties@npm:7.29.7" dependencies: - "@babel/helper-plugin-utils": ^7.27.1 + "@babel/helper-plugin-utils": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: fbba6e2aef0b69681acb68202aa249c0598e470cc0853d7ff5bd0171fd6a7ec31d77cfabcce9df6360fc8349eded7e4a65218c32551bd3fc0caaa1ac899ac6d4 + checksum: c57ef27853f334a6147da9aa00f8a8f4c3a1c217eb2efa73cba2e118edda10754fa23cec2c0c7f7408279ad28fef92c1f663dfec137a7503813331569c3e02f9 languageName: node linkType: hard -"@babel/plugin-transform-spread@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/plugin-transform-spread@npm:7.28.6" +"@babel/plugin-transform-spread@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-spread@npm:7.29.7" dependencies: - "@babel/helper-plugin-utils": ^7.28.6 - "@babel/helper-skip-transparent-expression-wrappers": ^7.27.1 + "@babel/helper-plugin-utils": ^7.29.7 + "@babel/helper-skip-transparent-expression-wrappers": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: e4782578904df68f7d2b3e865f20701c71d6aba0027c4794c1dc08a2f805a12892a078dab483714552398a689ad4ff6786cdf4e088b073452aee7db67e37a09c + checksum: eb25f24d9a5cac163fea91b5872ff2ddb892083624284a6e8a1fa8dfc4c4c6f6230f3b478405eb846df895a3f96631ac19e8c169af33012aafaa144e6192d5d3 languageName: node linkType: hard -"@babel/plugin-transform-sticky-regex@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-sticky-regex@npm:7.27.1" +"@babel/plugin-transform-sticky-regex@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-sticky-regex@npm:7.29.7" dependencies: - "@babel/helper-plugin-utils": ^7.27.1 + "@babel/helper-plugin-utils": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: e1414a502efba92c7974681767e365a8cda6c5e9e5f33472a9eaa0ce2e75cea0a9bef881ff8dda37c7810ad902f98d3c00ead92a3ac3b73a79d011df85b5a189 + checksum: 16b570c0270a59c2a29b2118c00e463882e9dda49b51a17dde3ae6b2886995d49f4bf2161a4c743ad1bca39d2aeb3ac963400e095682e105c7f751e6a2156c28 languageName: node linkType: hard -"@babel/plugin-transform-template-literals@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-template-literals@npm:7.27.1" +"@babel/plugin-transform-template-literals@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-template-literals@npm:7.29.7" dependencies: - "@babel/helper-plugin-utils": ^7.27.1 + "@babel/helper-plugin-utils": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 93aad782503b691faef7c0893372d5243df3219b07f1f22cfc32c104af6a2e7acd6102c128439eab15336d048f1b214ca134b87b0630d8cd568bf447f78b25ce + checksum: d1014dab020f0f802089de17bba82d929eda6ac87fde5f58fb9763885b8d645ce63fc1df97055c06a12d95a8788334a93b559fcaf1da6d7777a191e5f9c5646e languageName: node linkType: hard -"@babel/plugin-transform-typeof-symbol@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-typeof-symbol@npm:7.27.1" +"@babel/plugin-transform-typeof-symbol@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-typeof-symbol@npm:7.29.7" dependencies: - "@babel/helper-plugin-utils": ^7.27.1 + "@babel/helper-plugin-utils": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: ed8048c8de72c60969a64cf2273cc6d9275d8fa8db9bd25a1268273a00fb9cbd79931140311411bda1443aa56cb3961fb911d1795abacde7f0482f1d8fdf0356 + checksum: 90c2308f97c4e3773b7d2010b962ce6122bd9e1163f0caf7bb45819342f547a5a41d36c73d9a828ad89ce2072e2613ea867d28ad59eb440d9e22196438437d02 languageName: node linkType: hard -"@babel/plugin-transform-unicode-escapes@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-unicode-escapes@npm:7.27.1" +"@babel/plugin-transform-unicode-escapes@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-unicode-escapes@npm:7.29.7" dependencies: - "@babel/helper-plugin-utils": ^7.27.1 + "@babel/helper-plugin-utils": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: d817154bc10758ddd85b716e0bc1af1a1091e088400289ab6b78a1a4d609907ce3d2f1fd51a6fd0e0c8ecbb5f8e3aab4957e0747776d132d2379e85c3ef0520a + checksum: cf337bf93a2e76aa82acb60d8a8a567225744cf7f42ffa4dde4c177aef54250f4067db38b8ab2c26f20cf2a589822242891ba8b91739a705f618bf6a4eeca7ff languageName: node linkType: hard -"@babel/plugin-transform-unicode-property-regex@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/plugin-transform-unicode-property-regex@npm:7.28.6" +"@babel/plugin-transform-unicode-property-regex@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-unicode-property-regex@npm:7.29.7" dependencies: - "@babel/helper-create-regexp-features-plugin": ^7.28.5 - "@babel/helper-plugin-utils": ^7.28.6 + "@babel/helper-create-regexp-features-plugin": ^7.29.7 + "@babel/helper-plugin-utils": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: d14e8c51aa73f592575c1543400fd67d96df6410d75c9dc10dd640fd7eecb37366a2f2368bbdd7529842532eda4af181c921bda95146c6d373c64ea59c6e9991 + checksum: 03ee0b5d27eee08ba71bc09e919eb648094123985b7adc7dc875e4172100596a47ab68337abf6814cbd3140c6552cf1044135eb0ec1ec78345e1270e5e6aabba languageName: node linkType: hard -"@babel/plugin-transform-unicode-regex@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-unicode-regex@npm:7.27.1" +"@babel/plugin-transform-unicode-regex@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-unicode-regex@npm:7.29.7" dependencies: - "@babel/helper-create-regexp-features-plugin": ^7.27.1 - "@babel/helper-plugin-utils": ^7.27.1 + "@babel/helper-create-regexp-features-plugin": ^7.29.7 + "@babel/helper-plugin-utils": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: a34d89a2b75fb78e66d97c3dc90d4877f7e31f43316b52176f95a5dee20e9bb56ecf158eafc42a001676ddf7b393d9e67650bad6b32f5405780f25fb83cd68e3 + checksum: 1ade0672ae5bbbf2ec1ea0a8de1b5d804ae414283215620097ab21cf7f05dae8916f5b0548a18c6f080ec17135018f5edd2d38f8fa9ca052af570cab5c712786 languageName: node linkType: hard -"@babel/plugin-transform-unicode-sets-regex@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/plugin-transform-unicode-sets-regex@npm:7.28.6" +"@babel/plugin-transform-unicode-sets-regex@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-unicode-sets-regex@npm:7.29.7" dependencies: - "@babel/helper-create-regexp-features-plugin": ^7.28.5 - "@babel/helper-plugin-utils": ^7.28.6 + "@babel/helper-create-regexp-features-plugin": ^7.29.7 + "@babel/helper-plugin-utils": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0 - checksum: 423971fe2eef9d18782b1c30f5f42613ee510e5b9c08760c5538a0997b36c34495acce261e0e37a27831f81330359230bd1f33c2e1822de70241002b45b7d68e + checksum: 680c22e2a63bffbf6798b0c2f599b06beb7ea4d29ee37a56c9192014143d396c479b12783d9c343e107fa491aeeb65b1ca774fd76825ffb306eef7fb5e7b4b2c languageName: node linkType: hard -"@babel/preset-env@npm:^7.29.3": - version: 7.29.3 - resolution: "@babel/preset-env@npm:7.29.3" +"@babel/preset-env@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/preset-env@npm:7.29.7" dependencies: - "@babel/compat-data": ^7.29.3 - "@babel/helper-compilation-targets": ^7.28.6 - "@babel/helper-plugin-utils": ^7.28.6 - "@babel/helper-validator-option": ^7.27.1 - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": ^7.28.5 - "@babel/plugin-bugfix-safari-class-field-initializer-scope": ^7.27.1 - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": ^7.27.1 - "@babel/plugin-bugfix-safari-rest-destructuring-rhs-array": ^7.29.3 - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": ^7.27.1 - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": ^7.28.6 + "@babel/compat-data": ^7.29.7 + "@babel/helper-compilation-targets": ^7.29.7 + "@babel/helper-plugin-utils": ^7.29.7 + "@babel/helper-validator-option": ^7.29.7 + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": ^7.29.7 + "@babel/plugin-bugfix-safari-class-field-initializer-scope": ^7.29.7 + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": ^7.29.7 + "@babel/plugin-bugfix-safari-rest-destructuring-rhs-array": ^7.29.7 + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": ^7.29.7 + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": ^7.29.7 "@babel/plugin-proposal-private-property-in-object": 7.21.0-placeholder-for-preset-env.2 - "@babel/plugin-syntax-import-assertions": ^7.28.6 - "@babel/plugin-syntax-import-attributes": ^7.28.6 + "@babel/plugin-syntax-import-assertions": ^7.29.7 + "@babel/plugin-syntax-import-attributes": ^7.29.7 "@babel/plugin-syntax-unicode-sets-regex": ^7.18.6 - "@babel/plugin-transform-arrow-functions": ^7.27.1 - "@babel/plugin-transform-async-generator-functions": ^7.29.0 - "@babel/plugin-transform-async-to-generator": ^7.28.6 - "@babel/plugin-transform-block-scoped-functions": ^7.27.1 - "@babel/plugin-transform-block-scoping": ^7.28.6 - "@babel/plugin-transform-class-properties": ^7.28.6 - "@babel/plugin-transform-class-static-block": ^7.28.6 - "@babel/plugin-transform-classes": ^7.28.6 - "@babel/plugin-transform-computed-properties": ^7.28.6 - "@babel/plugin-transform-destructuring": ^7.28.5 - "@babel/plugin-transform-dotall-regex": ^7.28.6 - "@babel/plugin-transform-duplicate-keys": ^7.27.1 - "@babel/plugin-transform-duplicate-named-capturing-groups-regex": ^7.29.0 - "@babel/plugin-transform-dynamic-import": ^7.27.1 - "@babel/plugin-transform-explicit-resource-management": ^7.28.6 - "@babel/plugin-transform-exponentiation-operator": ^7.28.6 - "@babel/plugin-transform-export-namespace-from": ^7.27.1 - "@babel/plugin-transform-for-of": ^7.27.1 - "@babel/plugin-transform-function-name": ^7.27.1 - "@babel/plugin-transform-json-strings": ^7.28.6 - "@babel/plugin-transform-literals": ^7.27.1 - "@babel/plugin-transform-logical-assignment-operators": ^7.28.6 - "@babel/plugin-transform-member-expression-literals": ^7.27.1 - "@babel/plugin-transform-modules-amd": ^7.27.1 - "@babel/plugin-transform-modules-commonjs": ^7.28.6 - "@babel/plugin-transform-modules-systemjs": ^7.29.0 - "@babel/plugin-transform-modules-umd": ^7.27.1 - "@babel/plugin-transform-named-capturing-groups-regex": ^7.29.0 - "@babel/plugin-transform-new-target": ^7.27.1 - "@babel/plugin-transform-nullish-coalescing-operator": ^7.28.6 - "@babel/plugin-transform-numeric-separator": ^7.28.6 - "@babel/plugin-transform-object-rest-spread": ^7.28.6 - "@babel/plugin-transform-object-super": ^7.27.1 - "@babel/plugin-transform-optional-catch-binding": ^7.28.6 - "@babel/plugin-transform-optional-chaining": ^7.28.6 - "@babel/plugin-transform-parameters": ^7.27.7 - "@babel/plugin-transform-private-methods": ^7.28.6 - "@babel/plugin-transform-private-property-in-object": ^7.28.6 - "@babel/plugin-transform-property-literals": ^7.27.1 - "@babel/plugin-transform-regenerator": ^7.29.0 - "@babel/plugin-transform-regexp-modifiers": ^7.28.6 - "@babel/plugin-transform-reserved-words": ^7.27.1 - "@babel/plugin-transform-shorthand-properties": ^7.27.1 - "@babel/plugin-transform-spread": ^7.28.6 - "@babel/plugin-transform-sticky-regex": ^7.27.1 - "@babel/plugin-transform-template-literals": ^7.27.1 - "@babel/plugin-transform-typeof-symbol": ^7.27.1 - "@babel/plugin-transform-unicode-escapes": ^7.27.1 - "@babel/plugin-transform-unicode-property-regex": ^7.28.6 - "@babel/plugin-transform-unicode-regex": ^7.27.1 - "@babel/plugin-transform-unicode-sets-regex": ^7.28.6 + "@babel/plugin-transform-arrow-functions": ^7.29.7 + "@babel/plugin-transform-async-generator-functions": ^7.29.7 + "@babel/plugin-transform-async-to-generator": ^7.29.7 + "@babel/plugin-transform-block-scoped-functions": ^7.29.7 + "@babel/plugin-transform-block-scoping": ^7.29.7 + "@babel/plugin-transform-class-properties": ^7.29.7 + "@babel/plugin-transform-class-static-block": ^7.29.7 + "@babel/plugin-transform-classes": ^7.29.7 + "@babel/plugin-transform-computed-properties": ^7.29.7 + "@babel/plugin-transform-destructuring": ^7.29.7 + "@babel/plugin-transform-dotall-regex": ^7.29.7 + "@babel/plugin-transform-duplicate-keys": ^7.29.7 + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": ^7.29.7 + "@babel/plugin-transform-dynamic-import": ^7.29.7 + "@babel/plugin-transform-explicit-resource-management": ^7.29.7 + "@babel/plugin-transform-exponentiation-operator": ^7.29.7 + "@babel/plugin-transform-export-namespace-from": ^7.29.7 + "@babel/plugin-transform-for-of": ^7.29.7 + "@babel/plugin-transform-function-name": ^7.29.7 + "@babel/plugin-transform-json-strings": ^7.29.7 + "@babel/plugin-transform-literals": ^7.29.7 + "@babel/plugin-transform-logical-assignment-operators": ^7.29.7 + "@babel/plugin-transform-member-expression-literals": ^7.29.7 + "@babel/plugin-transform-modules-amd": ^7.29.7 + "@babel/plugin-transform-modules-commonjs": ^7.29.7 + "@babel/plugin-transform-modules-systemjs": ^7.29.7 + "@babel/plugin-transform-modules-umd": ^7.29.7 + "@babel/plugin-transform-named-capturing-groups-regex": ^7.29.7 + "@babel/plugin-transform-new-target": ^7.29.7 + "@babel/plugin-transform-nullish-coalescing-operator": ^7.29.7 + "@babel/plugin-transform-numeric-separator": ^7.29.7 + "@babel/plugin-transform-object-rest-spread": ^7.29.7 + "@babel/plugin-transform-object-super": ^7.29.7 + "@babel/plugin-transform-optional-catch-binding": ^7.29.7 + "@babel/plugin-transform-optional-chaining": ^7.29.7 + "@babel/plugin-transform-parameters": ^7.29.7 + "@babel/plugin-transform-private-methods": ^7.29.7 + "@babel/plugin-transform-private-property-in-object": ^7.29.7 + "@babel/plugin-transform-property-literals": ^7.29.7 + "@babel/plugin-transform-regenerator": ^7.29.7 + "@babel/plugin-transform-regexp-modifiers": ^7.29.7 + "@babel/plugin-transform-reserved-words": ^7.29.7 + "@babel/plugin-transform-shorthand-properties": ^7.29.7 + "@babel/plugin-transform-spread": ^7.29.7 + "@babel/plugin-transform-sticky-regex": ^7.29.7 + "@babel/plugin-transform-template-literals": ^7.29.7 + "@babel/plugin-transform-typeof-symbol": ^7.29.7 + "@babel/plugin-transform-unicode-escapes": ^7.29.7 + "@babel/plugin-transform-unicode-property-regex": ^7.29.7 + "@babel/plugin-transform-unicode-regex": ^7.29.7 + "@babel/plugin-transform-unicode-sets-regex": ^7.29.7 "@babel/preset-modules": 0.1.6-no-external-plugins babel-plugin-polyfill-corejs2: ^0.4.15 babel-plugin-polyfill-corejs3: ^0.14.0 @@ -1528,7 +1603,7 @@ __metadata: semver: ^6.3.1 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: bc07d151dbbcee339e9f7f68876b8d89798e01bc0a04d44c92460be61ac7bdc34810e81bc99055dc01305c86350fd8b54969fc907aa405702824b9b96917028d + checksum: 36deae2ea4329e8490fc4507e6747e07c4cff9df1f1397aa99fae16e03a5195f9c7a3494f571ddfb5002bbc0e18832a8cc711831d686896312fa127823f7fedc languageName: node linkType: hard @@ -1545,19 +1620,19 @@ __metadata: languageName: node linkType: hard -"@babel/preset-react@npm:^7.28.5": - version: 7.28.5 - resolution: "@babel/preset-react@npm:7.28.5" +"@babel/preset-react@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/preset-react@npm:7.29.7" dependencies: - "@babel/helper-plugin-utils": ^7.27.1 - "@babel/helper-validator-option": ^7.27.1 - "@babel/plugin-transform-react-display-name": ^7.28.0 - "@babel/plugin-transform-react-jsx": ^7.27.1 - "@babel/plugin-transform-react-jsx-development": ^7.27.1 - "@babel/plugin-transform-react-pure-annotations": ^7.27.1 + "@babel/helper-plugin-utils": ^7.29.7 + "@babel/helper-validator-option": ^7.29.7 + "@babel/plugin-transform-react-display-name": ^7.29.7 + "@babel/plugin-transform-react-jsx": ^7.29.7 + "@babel/plugin-transform-react-jsx-development": ^7.29.7 + "@babel/plugin-transform-react-pure-annotations": ^7.29.7 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 13bc1fe4dde0a29d00323e46749e5beb457844507cb3afa2fefbd85d283c2d4836f9e4a780be735de58a44c505870476dc2838f1f8faf9d6f056481e65f1a0fb + checksum: ec9d4d418df3825674ef807020b90a93d6bf6b786a723a59e673c3a32e31927b2f8a50071a17a50fff632f41eda8933e4196974130f2a5cdeb1a040fb2b62b76 languageName: node linkType: hard @@ -1568,10 +1643,10 @@ __metadata: languageName: node linkType: hard -"@babel/runtime@npm:^7.29.2": - version: 7.29.2 - resolution: "@babel/runtime@npm:7.29.2" - checksum: d5548d1165de8995f8afc93a5694b8625409be16cd1f2250ac13e331335858ddac3cb9fd278e6c43956a130101a2203f09417938a1a96f9fb70f02b4b4172e1d +"@babel/runtime@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/runtime@npm:7.29.7" + checksum: bc311855c6dbf5356030979584ca0f8b6cee39fe058175b02e85a73e246fc76ae30248b0d40e70c2652101faeb43279468ed2d086a670673eb9783c1fee1df2b languageName: node linkType: hard @@ -1586,14 +1661,14 @@ __metadata: languageName: node linkType: hard -"@babel/template@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/template@npm:7.28.6" +"@babel/template@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/template@npm:7.29.7" dependencies: - "@babel/code-frame": ^7.28.6 - "@babel/parser": ^7.28.6 - "@babel/types": ^7.28.6 - checksum: 8ab6383053e226025d9491a6e795293f2140482d14f60c1244bece6bf53610ed1e251d5e164de66adab765629881c7d9416e1e540c716541d2fd0f8f36a013d7 + "@babel/code-frame": ^7.29.7 + "@babel/parser": ^7.29.7 + "@babel/types": ^7.29.7 + checksum: 521eb6a1fd4735074ca8dac0d70810860a80edf3bf78105851571993cd13701a2041987e7398ccc9376eb6235ea1258bf494ccaccf3b67fa98dbe954154a2e93 languageName: node linkType: hard @@ -1612,18 +1687,18 @@ __metadata: languageName: node linkType: hard -"@babel/traverse@npm:^7.28.6, @babel/traverse@npm:^7.29.0": - version: 7.29.0 - resolution: "@babel/traverse@npm:7.29.0" +"@babel/traverse@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/traverse@npm:7.29.7" dependencies: - "@babel/code-frame": ^7.29.0 - "@babel/generator": ^7.29.0 - "@babel/helper-globals": ^7.28.0 - "@babel/parser": ^7.29.0 - "@babel/template": ^7.28.6 - "@babel/types": ^7.29.0 + "@babel/code-frame": ^7.29.7 + "@babel/generator": ^7.29.7 + "@babel/helper-globals": ^7.29.7 + "@babel/parser": ^7.29.7 + "@babel/template": ^7.29.7 + "@babel/types": ^7.29.7 debug: ^4.3.1 - checksum: fbb5085aa525b5d4ecd9fe2f5885d88413fff6ad9c0fac244c37f96069b6d3af9ce825750cd16af1d97d26fa3d354b38dbbdb5f31430e0d99ed89660ab65430e + checksum: 6c4508fd2a308a6a41fbf40bd2590bccfdc3903de51c640a928c49e810220b9e27323a083cda604d44a27449b57265a701b549de01f479611390863734b4fd38 languageName: node linkType: hard @@ -1637,13 +1712,13 @@ __metadata: languageName: node linkType: hard -"@babel/types@npm:^7.28.6, @babel/types@npm:^7.29.0": - version: 7.29.0 - resolution: "@babel/types@npm:7.29.0" +"@babel/types@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/types@npm:7.29.7" dependencies: - "@babel/helper-string-parser": ^7.27.1 - "@babel/helper-validator-identifier": ^7.28.5 - checksum: 83f190438e94c22b2574aaeef7501830311ef266eaabfb06523409f64e2fe855e522951607085d71cad286719adef14e1ba37b671f334a7cd25b0f8506a01e0b + "@babel/helper-string-parser": ^7.29.7 + "@babel/helper-validator-identifier": ^7.29.7 + checksum: 71c46837d22c5c63a5ed571f3b68b4261ecabfc3d4be7251b336ccbd26bc52752ae68ae6d16d24ea512311b78b6f54efdfb00dde87a81a4dc3d19e4a45f05b20 languageName: node linkType: hard @@ -5563,12 +5638,12 @@ __metadata: version: 0.0.0-use.local resolution: "courseography@workspace:." dependencies: - "@babel/core": ^7.29.0 - "@babel/eslint-parser": ^7.28.6 + "@babel/core": ^7.29.7 + "@babel/eslint-parser": ^7.29.7 "@babel/plugin-proposal-class-properties": ^7.18.6 - "@babel/preset-env": ^7.29.3 - "@babel/preset-react": ^7.28.5 - "@babel/runtime": ^7.29.2 + "@babel/preset-env": ^7.29.7 + "@babel/preset-react": ^7.29.7 + "@babel/runtime": ^7.29.7 "@emotion/react": ^11.14.0 "@emotion/styled": ^11.14.1 "@eslint/compat": ^1.2.9 From 432042ecbac79b89d21ab9b2086ee17275ac3251 Mon Sep 17 00:00:00 2001 From: Angelina Jiang <43974738+AngelsandDevsLOL@users.noreply.github.com> Date: Sun, 7 Jun 2026 14:17:15 -0400 Subject: [PATCH 12/39] Renamed Course data type to CourseData (#1721) --- CHANGELOG.md | 1 + app/Database/Tables.hs | 15 ------------ app/Models/Course.hs | 53 ++++++++++++++++++++++++++++++++---------- app/Models/Meeting.hs | 4 ++-- 4 files changed, 44 insertions(+), 29 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f3cdd88d..f734a2748 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,7 @@ - Refactor graph helper functions from `app/Svg/Database.hs` to `app/Models/Graph.hs` - Refactor functions for performing matrix operations from `app/Svg/Parser.hs` to `app/Util/Matrix.hs` - Updated documentation in `app/Util/Blaze.hs` +- Moved the `Course` data type from `Database/Tables.hs` into `Models/Course.hs`, renamed it to `CourseData` - Removed `SvgJSON` data type in favour of `([Text], [Shape], [Path])` ## [0.7.2] - 2025-12-10 diff --git a/app/Database/Tables.hs b/app/Database/Tables.hs index 6249761fc..75431190d 100644 --- a/app/Database/Tables.hs +++ b/app/Database/Tables.hs @@ -183,21 +183,6 @@ data MeetTime = MeetTime {meetInfo :: Meeting, timeInfo :: [Time'] } data MeetTime' = MeetTime' { meetData :: Meeting, timeData :: [Time] } deriving (Show, Generic) --- | A Course. TODO: remove this data type (it's redundant). -data Course = - Course { breadth :: Maybe T.Text, - description :: Maybe T.Text, - title :: Maybe T.Text, - prereqString :: Maybe T.Text, - allMeetingTimes :: Maybe [MeetTime'], - name :: !T.Text, - exclusions :: Maybe T.Text, - distribution :: Maybe T.Text, - coreqs :: Maybe T.Text, - videoUrls :: [T.Text] - } deriving (Show, Generic) - -instance ToJSON Course instance ToJSON Program instance ToJSON Time instance ToJSON MeetTime' diff --git a/app/Models/Course.hs b/app/Models/Course.hs index 05946ae5b..9ce303f69 100644 --- a/app/Models/Course.hs +++ b/app/Models/Course.hs @@ -1,5 +1,8 @@ +{-# LANGUAGE DeriveGeneric #-} + module Models.Course - (buildCourse, + (CourseData (..), + buildCourse, returnCourse, prereqsForCourse, getDeptCourses, @@ -7,17 +10,43 @@ module Models.Course import Config (runDb) import Control.Monad.IO.Class (MonadIO, liftIO) +import Data.Aeson (ToJSON) import Data.Maybe (fromMaybe) import qualified Data.Text as T (Text, append, filter, snoc, toUpper) import Database.Persist.Class (selectKeysList) import Database.Persist.Sqlite (Entity, PersistValue (PersistText), SqlPersistM, entityVal, get, insert_, rawSql, selectFirst, selectList, (<-.), (==.)) -import Database.Tables hiding (breadth, distribution) +import Database.Tables (Breadth (breadthDescription), + Courses (coursesBreadth, coursesCode, coursesCoreqs, coursesDescription, coursesDistribution, coursesExclusions, coursesPrereqString, coursesTitle, coursesVideoUrls), + Distribution (distributionDescription), + EntityField (BreadthDescription, CoursesCode, DistributionDescription, MeetingCode), + Key, MeetTime', Meeting (meetingCode)) +import GHC.Generics (Generic) import Models.Meeting (buildMeetTimes, meetingQuery) --- | Queries the database for all information about @course@, --- constructs and returns a Course value. -returnCourse :: T.Text -> IO (Maybe Course) +-- | The data for a single course, as returned by the back-end to the front-end. +-- This is different from the schema-defined 'Courses' type (in "Database.Tables") +-- 'Courses' describes how a course is stored in the database, whereas +-- 'CourseData' describes the shape of the information sent to the client +-- when a course is requested. +data CourseData = + CourseData { breadth :: Maybe T.Text, + description :: Maybe T.Text, + title :: Maybe T.Text, + prereqString :: Maybe T.Text, + allMeetingTimes :: Maybe [MeetTime'], + name :: !T.Text, + exclusions :: Maybe T.Text, + distribution :: Maybe T.Text, + coreqs :: Maybe T.Text, + videoUrls :: [T.Text] + } deriving (Show, Generic) + +instance ToJSON CourseData + +-- | Queries the database for all information about 'CourseData', +-- constructs and returns a 'CourseData' value. +returnCourse :: T.Text -> IO (Maybe CourseData) returnCourse lowerStr = runDb $ do let courseStr = T.toUpper lowerStr -- TODO: require the client to pass the full course code @@ -44,13 +73,13 @@ getDescriptionD (Just key) = do maybeDistribution <- get key return $ fmap distributionDescription maybeDistribution --- | Builds a Course structure from a tuple from the Courses table. +-- | Builds a 'CourseData' structure from a tuple from the Courses table. -- Some fields still need to be added in. -buildCourse :: [MeetTime'] -> Courses -> SqlPersistM Course +buildCourse :: [MeetTime'] -> Courses -> SqlPersistM CourseData buildCourse allMeetings course = do cBreadth <- getDescriptionB (coursesBreadth course) cDistribution <- getDescriptionD (coursesDistribution course) - return $ Course cBreadth + return $ CourseData cBreadth -- TODO: Remove the filter and allow double-quotes (fmap (T.filter (/='\"')) (coursesDescription course)) (fmap (T.filter (/='\"')) (coursesTitle course)) @@ -77,7 +106,7 @@ prereqsForCourse courseCode = runDb $ do fromMaybe "" $ coursesPrereqString $ entityVal courseEntity) ) :: SqlPersistM (Either String (T.Text, T.Text)) -getDeptCourses :: MonadIO m => T.Text -> m [Course] +getDeptCourses :: MonadIO m => T.Text -> m [CourseData] getDeptCourses dept = liftIO $ runDb $ do courses :: [Entity Courses] <- rawSql "SELECT ?? FROM courses WHERE code LIKE ?" [PersistText $ T.snoc dept '%'] let deptCourses = map entityVal courses @@ -111,10 +140,10 @@ getBreadthKey description_ = do -- | Inserts course into the Courses table. insertCourse :: (Courses, T.Text, T.Text) -> SqlPersistM () -insertCourse (course, breadth, distribution) = do +insertCourse (course, breadthDesc, distributionDesc) = do maybeCourse <- selectFirst [CoursesCode ==. coursesCode course] [] - breadthKey <- getBreadthKey breadth - distributionKey <- getDistributionKey distribution + breadthKey <- getBreadthKey breadthDesc + distributionKey <- getDistributionKey distributionDesc case maybeCourse of Nothing -> insert_ $ course {coursesBreadth = breadthKey, coursesDistribution = distributionKey} diff --git a/app/Models/Meeting.hs b/app/Models/Meeting.hs index 86f536214..270fbb72e 100644 --- a/app/Models/Meeting.hs +++ b/app/Models/Meeting.hs @@ -26,7 +26,7 @@ buildMeetTimes meet = do return $ Tables.MeetTime' (entityVal meet) parsedTime -- | Queries the database for all information regarding a specific meeting for --- a @course@, returns a Meeting. +-- a course, returns a Meeting. returnMeeting :: T.Text -> T.Text -> T.Text -> SqlPersistM (Maybe (Entity Meeting)) returnMeeting lowerStr sect session = do selectFirst [MeetingCode ==. T.toUpper lowerStr, @@ -35,7 +35,7 @@ returnMeeting lowerStr sect session = do [] -- | Queries the database for all times regarding a specific meeting (lecture, tutorial or practial) for --- a @course@, returns a list of Time. +-- a course, returns a list of Time. getMeetingTime :: (T.Text, T.Text, T.Text) -> SqlPersistM [Time] getMeetingTime (meetingCode_, meetingSection_, meetingSession_) = do maybeEntityMeetings <- selectFirst [MeetingCode ==. meetingCode_, From 14b37a4a7087d62aa5666d49d81d9eb611baf374 Mon Sep 17 00:00:00 2001 From: David Liu Date: Tue, 9 Jun 2026 09:54:46 -0400 Subject: [PATCH 13/39] Updated CS graph and config for 2026-27 (#1726) --- CHANGELOG.md | 2 + app/Config.hs | 2 +- app/Svg/Parser.hs | 8 +- config.yaml | 33 +- graphs/csc2026.graphml | 2524 +++++++++++++++++++++ graphs/csc2026.svg | 4740 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 7289 insertions(+), 20 deletions(-) create mode 100644 graphs/csc2026.graphml create mode 100644 graphs/csc2026.svg diff --git a/CHANGELOG.md b/CHANGELOG.md index f734a2748..f968be653 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,11 +7,13 @@ ### ✨ New features/enhancements - Added 404 status code return to `retrieveCourse` in `Controllers/Course` and added front-end tests for affected components +- Updated Computer Science graph and configuration for 2026-27 ### 🐛 Bug fixes - Fixed a bug where duplicate graph components were being added - Fixed CSS styling to center course modal and lighten overlay +- Fixed a bug in SVG parsing where `path` elements with a `Z` path directive were not being ignored ### 🔧 Internal changes diff --git a/app/Config.hs b/app/Config.hs index 07943216c..b1fce49c3 100644 --- a/app/Config.hs +++ b/app/Config.hs @@ -183,7 +183,7 @@ createReqBody page = object [ "campuses" .= ([] :: [T.Text]), "page" .= page, "pageSize" .= (300 :: Int), "requirementProps" .= ([] :: [T.Text]), - "sessions" .= (["20259", "20261"] :: [T.Text]), + "sessions" .= (["20269", "20271"] :: [T.Text]), "timePreferences" .= ([] :: [T.Text]) ] diff --git a/app/Svg/Parser.hs b/app/Svg/Parser.hs index 85b60c11e..79b69f5bc 100644 --- a/app/Svg/Parser.hs +++ b/app/Svg/Parser.hs @@ -18,7 +18,7 @@ module Svg.Parser import Config (graphPath, runDb) import Control.Monad.IO.Class (liftIO) -import Data.Char (isSpace) +import Data.Char (isSpace, toLower) import qualified Data.List as List import Data.Maybe (fromMaybe) import qualified Data.Text as T @@ -41,7 +41,7 @@ import Util.Matrix (matrixMultiply) parsePrebuiltSvgs :: IO () parsePrebuiltSvgs = runDb $ do - performParse "Computer Science" "csc2025.svg" + performParse "Computer Science" "csc2026.svg" performParse "Statistics" "sta2022.svg" -- performParse "(unofficial) Mathematics Specialist" "math_specialist2022.svg" -- performParse "(unofficial) Biochemistry" "bch2015.svg" @@ -296,7 +296,9 @@ parsePathHelper key trans globalTrans (src, dst) pathTag = isRegion src dst - [a, b, c, d', e, f] | not (T.null d || null realD || (T.last d == 'z' && not isRegion)) + [a, b, c, d', e, f] + -- Ignore empty paths and non-region paths that are loops (these are arrowheads in the raw SVG) + | not (T.null d || null realD || (toLower (T.last d) == 'z' && not isRegion)) ] where -- Remove consecutive duplicated points diff --git a/config.yaml b/config.yaml index e378adb03..7f2e22ac2 100644 --- a/config.yaml +++ b/config.yaml @@ -17,22 +17,23 @@ fasCalendarUrl: "https://artsci.calendar.utoronto.ca/" programsUrl: "https://artsci.calendar.utoronto.ca/listing-program-subject-areas" # Term dates -fallStartDate: 2025-09-02 -fallEndDate: 2025-12-02 -winterStartDate: 2026-01-05 -winterEndDate: 2026-04-02 -outDay: 2027-01-01 +fallStartDate: 2026-09-08 +fallEndDate: 2026-12-07 +winterStartDate: 2027-01-11 +winterEndDate: 2027-04-09 +outDay: 2028-01-01 # Holidays holidaysList: - - 20251013T - - 20251027T - - 20251028T - - 20251029T - - 20251030T - - 20251130T - - 20260216T - - 20260217T - - 20260218T - - 20260219T - - 20260220T + - 20261012T + - 20261026T + - 20261027T + - 20261028T + - 20261029T + - 20261030T + - 20270215T + - 20270216T + - 20270217T + - 20270218T + - 20270219T + - 20270326T diff --git a/graphs/csc2026.graphml b/graphs/csc2026.graphml new file mode 100644 index 000000000..99c566119 --- /dev/null +++ b/graphs/csc2026.graphml @@ -0,0 +1,2524 @@ + + + + + + + + + + + + + + + + + + + + + + + CSC108H1 + + + + + + + + + + + CSC148H1 + + + + + + + + + + + CSC165H1 + + + + + + + + + + + CSC110Y1 + + + + + + + + + + + CSC111H1 + + + + + + + + + + + CSC236H1 + + + + + + + + + + + CSC240H1 + + + + + + + + + + + CSC263H1 + + + + + + + + + + + CSC265H1 + + + + + + + + + + + CSC373H1 + + + + + + + + + + + CSC374H1 + + + + + + + + + + + CSC473H1 + + + + + + + + + + + CSC310H1 + + + + + + + + + + + CSC438H1 + + + + + + + + + + + CSC463H1 + + + + + + + + + + + CSC207H1 + + + + + + + + + + + CSC301H1 + + + + + + + + + + + CSC302H1 + + + + + + + + + + + CSC324H1 + + + + + + + + + + + CSC488H1 + + + + + + + + + + + CSC465H1 + + + + + + + + + + + CSC410H1 + + + + + + + + + + + CSC258H1 + + + + + + + + + + + CSC209H1 + + + + + + + + + + + CSC309H1 + + + + + + + + + + + CSC343H1 + + + + + + + + + + + CSC369H1 + + + + + + + + + + + CSC469H1 + + + + + + + + + + + CSC443H1 + + + + + + + + + + + CSC385H1 + + + + + + + + + + + CSC368H1 + + + + + + + + + + + CSC457H1 + + + + + + + + + + + CSC458H1 + + + + + + + + + + + CSC303H1 + + + + + + + + + + + CSC304H1 + + + + + + + + + + + CSC300H1 + + + + + + + + + + + CSC318H1 + + + + + + + + + + + CSC428H1 + + + + + + + + + + + CSC316H1 + + + + + + + + + + + CSC404H1 + + + + + + + + + + + CSC308H1 + + + + + + + + + + + CSC454H1 + + + + + + + + + + + CSC311H1 + + + + + + + + + + + CSC384H1 + + + + + + + + + + + CSC486H1 + + + + + + + + + + + CSC412H1 + + + + + + + + + + + CSC413H1 + + + + + + + + + + + CSC401H1 + + + + + + + + + + + CSC485H1 + + + + + + + + + + + CSC320H1 + + + + + + + + + + + CSC420H1 + + + + + + + + + + + CSC317H1 + + + + + + + + + + + CSC417H1 + + + + + + + + + + + CSC419H1 + + + + + + + + + + + CSC336H1 + + + + + + + + + + + CSC436H1 + + + + + + + + + + + CSC446H1 + + + + + + + + + + + CSC456H1 + + + + + + + + + + + CSC466H1 + + + + + + + + + + + CSC194H1 + + + + + + + + + + + CSC196H1 + + + + + + + + + + + CSC197H1 + + + + + + + + + + + CSC199H1 + + + + + + + + + + + MAT135H1 + + + + + + + + + + + MAT136H1 + + + + + + + + + + + MAT223H1 + + + + + + + + + + + MAT240H1 + + + + + + + + + + + STA237H1/STA247H1/ +STA255H1/STA257H1 + + + + + + + + + + + + (MAT235H1, MAT236H1)/ +MAT237Y1/MAT257Y1 + + + + + + + + + + + + STA237H1/STA247H1/ +STA255H1/STA257H1 + + + + + + + + + + + + and + + + + + + + + + + + + or + + + + + + + + + + + + or + + + + + + + + + + + + or + + + + + + + + + + + + or + + + + + + + + + + + + or + + + + + + + + + + + + or + + + + + + + + + + + + CSC373H1 + + + + + + + + + + + + or + + + + + + + + + + + + CSC209H1 + + + + + + + + + + + + CSC263H1/CSC265H1 + + + + + + + + + + + + and + + + + + + + + + + + + CSC301H1/CSC317H1/CSC318H1/ +CSC384H1/CSC417H1/CSC419H1 + + + + + + + + + + + + CSC111H1/CSC148H1, +MAT223H1/MAT240H1 + + + + + + + + + + + + CSC207H1 + + + + + + + + + + + + and + + + + + + + + + + + CSC367H1 + + + + + + + + + + + + MAT223H1/ +MAT240H1 + + + + + + + + + + + CSC364H1 + + + + + + + + + + + CSC448H1 + + + + + + + + + + + MAT224H1/ +MAT247H1 + + + + + + + + + + + MAT148H1 + + + + + + + + + + + MAT149H1 + + + + + + + + + + + MAT158H1 + + + + + + + + + + + MAT159H1 + + + + + + + + + + + MAT235H1 + + + + + + + + + + + MAT236H1 + + + + + + + + + + + MAT237Y1 + + + + + + + + + + + MAT257Y1 + + + + + + + + + + + + or + + + + + + + + + + + CSC491H1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/graphs/csc2026.svg b/graphs/csc2026.svg new file mode 100644 index 000000000..88af4e4b7 --- /dev/null +++ b/graphs/csc2026.svg @@ -0,0 +1,4740 @@ + + + +Mathematics and StatisticsIntroductory CoursesTheory of ComputingArtificial IntelligenceSoftware EngineeringComputer SystemsHuman-Computer Interaction +and Computer GraphicsScientific Computing From 95edff2c72a2625af435e8e9baafc7f63bd06290 Mon Sep 17 00:00:00 2001 From: David Liu Date: Tue, 9 Jun 2026 10:44:51 -0400 Subject: [PATCH 14/39] Added privacy-preserving analytics using GoatCounter and updated privacy policy (#1727) --- CHANGELOG.md | 1 + PRIVACY.md | 12 ++++++------ app/MasterTemplate.hs | 4 ++++ 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f968be653..613b6f1cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ - Added 404 status code return to `retrieveCourse` in `Controllers/Course` and added front-end tests for affected components - Updated Computer Science graph and configuration for 2026-27 +- Added privacy-preserving analytics using GoatCounter and updated privacy policy ### 🐛 Bug fixes diff --git a/PRIVACY.md b/PRIVACY.md index 3c296bc6b..dab680d5e 100644 --- a/PRIVACY.md +++ b/PRIVACY.md @@ -1,15 +1,15 @@ -#Privacy Policy +# Privacy Policy -Courseography does not store any information about you: none of your actions in the various components of this website are recorded, nor is any of your information accessed through Facebook. +Courseography does not collect or store any information about you, and does not require sign-in to use any website features. -There is an option for you to post schedules and graphs to your Facebook account. At no point will Courseography post anything to Facebook without your instruction to do so. Courseography does not interact with your Facebook account in any way other than these posts, and logging in and out. Logging into your Facebook account is not required to use any other feature of this website. +Courseography uses [GoatCounter](https://www.goatcounter.com/), an open-source web analytics platform to track page views. This platform does not store any personal information about you, and does not use cookies or persistent storage to track you. For information about GoatCounter, please see its [Privacy Policy](https://www.goatcounter.com/help/privacy). -##Changes to this privacy statement +## Changes to this privacy statement We may amend this Privacy Statement from time to time. If we make changes in the way we use personal information, we will notify you by posting an announcement on our website. Users are bound by any changes to the Privacy Statement when he or she uses or otherwise accesses Courseography after such changes have been first posted. -##Questions or concerns +## Questions or concerns If you have any questions or concerns regarding privacy on our website, please send us a detailed message at courseography@cs.toronto.edu. We will make every effort to resolve your concerns. -Effective Date: April 15, 2015 +Effective Date: June 6, 2025 diff --git a/app/MasterTemplate.hs b/app/MasterTemplate.hs index e4b5295ba..f861ee9e0 100644 --- a/app/MasterTemplate.hs +++ b/app/MasterTemplate.hs @@ -20,6 +20,10 @@ masterTemplate title headers body scripts = ! A.href "/static/res/ico/favicon.png" sequence_ headers toStylesheet "/static/style/app.css" + H.script ! H.customAttribute "data-goatcounter" "https://david-yz-liu.goatcounter.com/count" + ! H.customAttribute "async" "" + ! A.src "//gc.zgo.at/count.js" + $ mempty H.body $ do body scripts From a46556b378ff196f4cbf5965278fd5adc7542cb4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Jun 2026 10:53:02 -0400 Subject: [PATCH 15/39] build(deps): bump the react group across 1 directory with 2 updates (#1700) Bumps the react group with 2 updates in the / directory: [react](https://github.com/facebook/react/tree/HEAD/packages/react) and [react-dom](https://github.com/facebook/react/tree/HEAD/packages/react-dom). Updates `react` from 19.2.4 to 19.2.7 - [Release notes](https://github.com/facebook/react/releases) - [Changelog](https://github.com/facebook/react/blob/main/CHANGELOG.md) - [Commits](https://github.com/facebook/react/commits/v19.2.7/packages/react) Updates `react-dom` from 19.2.4 to 19.2.7 - [Release notes](https://github.com/facebook/react/releases) - [Changelog](https://github.com/facebook/react/blob/main/CHANGELOG.md) - [Commits](https://github.com/facebook/react/commits/v19.2.7/packages/react-dom) --- updated-dependencies: - dependency-name: react dependency-version: 19.2.5 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: react - dependency-name: react-dom dependency-version: 19.2.5 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: react ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 4 ++-- yarn.lock | 22 +++++++++++----------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/package.json b/package.json index cf85c4322..4f88b965f 100644 --- a/package.json +++ b/package.json @@ -41,8 +41,8 @@ "jquery": "^3.7.1", "leaflet": "^1.9.3", "lodash": "^4.18.1", - "react": "^19.2.4", - "react-dom": "^19.2.4", + "react": "^19.2.7", + "react-dom": "^19.2.7", "react-error-boundary": "^5.0.0", "react-leaflet": "^4.2.1", "react-modal": "^3.16.1", diff --git a/yarn.lock b/yarn.lock index 189a8b0fc..de525359c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5685,8 +5685,8 @@ __metadata: precise-commits: 1.0.2 prettier: ^3.7.4 prop-types: 15.8.1 - react: ^19.2.4 - react-dom: ^19.2.4 + react: ^19.2.7 + react-dom: ^19.2.7 react-error-boundary: ^5.0.0 react-leaflet: ^4.2.1 react-modal: ^3.16.1 @@ -11099,14 +11099,14 @@ __metadata: languageName: node linkType: hard -"react-dom@npm:^19.2.4": - version: 19.2.4 - resolution: "react-dom@npm:19.2.4" +"react-dom@npm:^19.2.7": + version: 19.2.7 + resolution: "react-dom@npm:19.2.7" dependencies: scheduler: ^0.27.0 peerDependencies: - react: ^19.2.4 - checksum: 2650391005468c228616d54431682e190068bfc2e68b9bf33582df637c4b60bfd9925bb6b4bfada2679a6a974d0e756c1db4a656c502e654d77b8a6b6ad162ea + react: ^19.2.7 + checksum: 9543b532a070c91751dd9aae77f5ee21d2aeada28e061080162433a5418f8ba98eadb869c76d82eff9f0475e5ff2b9e1cf31916ab6509f8ebc856be77361eb1c languageName: node linkType: hard @@ -11226,10 +11226,10 @@ __metadata: languageName: node linkType: hard -"react@npm:^19.2.4": - version: 19.2.4 - resolution: "react@npm:19.2.4" - checksum: edf2b96619fab3a8b11714f16a0994a92c6b473aecf3269b63e4fa317d3073d40513c1f19cf4415ebbad94d35b48ff76ad768480db663037e2d929e8d60596b8 +"react@npm:^19.2.7": + version: 19.2.7 + resolution: "react@npm:19.2.7" + checksum: be94ec2f1779b27cac328ddae18e52933c2977a2425b67039229ead45c62d0363b66e894076236616c8d98821a9a760fcbab8a9da8ae9c4b2849dfd12cc32a46 languageName: node linkType: hard From 35a47ad875247d245d02b75d3ebb8955b399e2c7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Jun 2026 10:53:28 -0400 Subject: [PATCH 16/39] build(deps): bump the ag-grid group across 1 directory with 2 updates (#1697) Bumps the ag-grid group with 2 updates in the / directory: [ag-grid-community](https://github.com/ag-grid/ag-grid) and [ag-grid-react](https://github.com/ag-grid/ag-grid). Updates `ag-grid-community` from 35.2.0 to 35.3.1 - [Release notes](https://github.com/ag-grid/ag-grid/releases) - [Commits](https://github.com/ag-grid/ag-grid/compare/release-35.2.0...release-35.3.1) Updates `ag-grid-react` from 35.2.0 to 35.3.1 - [Release notes](https://github.com/ag-grid/ag-grid/releases) - [Commits](https://github.com/ag-grid/ag-grid/compare/release-35.2.0...release-35.3.1) --- updated-dependencies: - dependency-name: ag-grid-community dependency-version: 35.2.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: ag-grid - dependency-name: ag-grid-react dependency-version: 35.2.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: ag-grid ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 4 ++-- yarn.lock | 32 ++++++++++++++++---------------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/package.json b/package.json index 4f88b965f..52c76ebf8 100644 --- a/package.json +++ b/package.json @@ -32,8 +32,8 @@ "@fortawesome/free-solid-svg-icons": "^7.2.0", "@fortawesome/react-fontawesome": "^3.3.1", "@mui/material": "^7.3.1", - "ag-grid-community": "^35.2.0", - "ag-grid-react": "^35.2.0", + "ag-grid-community": "^35.3.1", + "ag-grid-react": "^35.3.1", "bootstrap": "^5.3.3", "core-js": "^3.42.0", "formik": "^2.4.6", diff --git a/yarn.lock b/yarn.lock index de525359c..32d266649 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4252,32 +4252,32 @@ __metadata: languageName: node linkType: hard -"ag-charts-types@npm:13.2.0": - version: 13.2.0 - resolution: "ag-charts-types@npm:13.2.0" - checksum: 9a78090bba9e90f45b468053d657c61f4dbce4fc0e69ed22cc8d3f5e4095d4b4d2bcc2eeb9edfda057ffd119e30c307433ec509a5c548c98ea7f330dde03a4a0 +"ag-charts-types@npm:13.3.1": + version: 13.3.1 + resolution: "ag-charts-types@npm:13.3.1" + checksum: 619a4cc091b2d3f5715780f34d2effc1926fce715b3cbe20b4b0d5fd6269ca56b3a00d3eb4db11377d36872214085ae8bc1dc7b24a945a63cec6a571525e5a5a languageName: node linkType: hard -"ag-grid-community@npm:35.2.0, ag-grid-community@npm:^35.2.0": - version: 35.2.0 - resolution: "ag-grid-community@npm:35.2.0" +"ag-grid-community@npm:35.3.1, ag-grid-community@npm:^35.3.1": + version: 35.3.1 + resolution: "ag-grid-community@npm:35.3.1" dependencies: - ag-charts-types: 13.2.0 - checksum: 0c0fcba50ee61a85b3cb651fff9415fc66089c15ffd2e61b275e5fc957ee4db2b2ef2a07e3cf4471285ce4b3394c72d2c940c55669e780c70b6c747f30a3ca7c + ag-charts-types: 13.3.1 + checksum: e87348cdeeeed6d5854e18f2ef8a757649502902383edeaeac8beede3460fb3a5de411593f5b111464052dca663f1413075db728fe44ff3f1020b318da0944d2 languageName: node linkType: hard -"ag-grid-react@npm:^35.2.0": - version: 35.2.0 - resolution: "ag-grid-react@npm:35.2.0" +"ag-grid-react@npm:^35.3.1": + version: 35.3.1 + resolution: "ag-grid-react@npm:35.3.1" dependencies: - ag-grid-community: 35.2.0 + ag-grid-community: 35.3.1 prop-types: ^15.8.1 peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - checksum: 777abeebe5073e276407265937f6db77528508e41cbc581ddb45a6945bccdd08318627c99d5a8ff8cd52ce85a6266d367c718ec4b89dd33080af2904c79b9035 + checksum: 066da99306b90a61b241d86687e9d2ef7de9ebe8d00113dd97dc4579a5d9b72d15f78386cc6e349ca54fe7e41b10b76e0e17d00f6675319a310a67480cd3d385 languageName: node linkType: hard @@ -5654,8 +5654,8 @@ __metadata: "@testing-library/dom": ^10.4.0 "@testing-library/react": ^16.0.1 "@testing-library/user-event": ^14.6.1 - ag-grid-community: ^35.2.0 - ag-grid-react: ^35.2.0 + ag-grid-community: ^35.3.1 + ag-grid-react: ^35.3.1 babel-jest: ^29.5.0 babel-loader: ^10.0.0 bootstrap: ^5.3.3 From 07281cfa87957cc75b6e3e43c75bbcc838bf8541 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Jun 2026 11:06:16 -0400 Subject: [PATCH 17/39] build(deps): bump shell-quote from 1.8.3 to 1.8.4 (#1728) Bumps [shell-quote](https://github.com/ljharb/shell-quote) from 1.8.3 to 1.8.4. - [Changelog](https://github.com/ljharb/shell-quote/blob/main/CHANGELOG.md) - [Commits](https://github.com/ljharb/shell-quote/compare/v1.8.3...v1.8.4) --- updated-dependencies: - dependency-name: shell-quote dependency-version: 1.8.4 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 32d266649..15d83c8ef 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11951,9 +11951,9 @@ __metadata: linkType: hard "shell-quote@npm:^1.8.3": - version: 1.8.3 - resolution: "shell-quote@npm:1.8.3" - checksum: 550dd84e677f8915eb013d43689c80bb114860649ec5298eb978f40b8f3d4bc4ccb072b82c094eb3548dc587144bb3965a8676f0d685c1cf4c40b5dc27166242 + version: 1.8.4 + resolution: "shell-quote@npm:1.8.4" + checksum: 082dc836baa8ade01144ee3068af487ea45ba570ea6ab13a5eddc11ab16a976b8857b51ef2caf7dc9a1e173ff0aea685b8f78b4f6f5a0a1ef24c7b17c51350e2 languageName: node linkType: hard From 8358a2669890e3b9869ea29ecdbcfc573337f256 Mon Sep 17 00:00:00 2001 From: David Liu Date: Tue, 9 Jun 2026 11:42:45 -0400 Subject: [PATCH 18/39] chore: Run yarn dedupe (#1729) --- yarn.lock | 593 +++--------------------------------------------------- 1 file changed, 32 insertions(+), 561 deletions(-) diff --git a/yarn.lock b/yarn.lock index 15d83c8ef..b5719f86d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18,18 +18,7 @@ __metadata: languageName: node linkType: hard -"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/code-frame@npm:7.27.1" - dependencies: - "@babel/helper-validator-identifier": ^7.27.1 - js-tokens: ^4.0.0 - picocolors: ^1.1.1 - checksum: 5874edc5d37406c4a0bb14cf79c8e51ad412fb0423d176775ac14fc0259831be1bf95bdda9c2aa651126990505e09a9f0ed85deaa99893bc316d2682c5115bdc - languageName: node - linkType: hard - -"@babel/code-frame@npm:^7.29.7": +"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.27.1, @babel/code-frame@npm:^7.29.7": version: 7.29.7 resolution: "@babel/code-frame@npm:7.29.7" dependencies: @@ -40,51 +29,14 @@ __metadata: languageName: node linkType: hard -"@babel/compat-data@npm:^7.27.2": - version: 7.28.5 - resolution: "@babel/compat-data@npm:7.28.5" - checksum: d7bcb3ee713752dc27b89800bfb39f9ac5f3edc46b4f5bb9906e1fe6b6110c7b245dd502602ea66f93790480c228605e9a601f27c07016f24b56772e97bedbdf - languageName: node - linkType: hard - -"@babel/compat-data@npm:^7.28.6": - version: 7.29.0 - resolution: "@babel/compat-data@npm:7.29.0" - checksum: ad19db279dfd06cbe91b505d03be00d603c6d3fcc141cfc14f4ace5c558193e9b6aae4788cb01fd209c4c850e52d73c8f3c247680e3c0d84fa17ab8b3d50c808 - languageName: node - linkType: hard - -"@babel/compat-data@npm:^7.29.7": +"@babel/compat-data@npm:^7.28.6, @babel/compat-data@npm:^7.29.7": version: 7.29.7 resolution: "@babel/compat-data@npm:7.29.7" checksum: 4424f8fb72f61657c8e811bdf7e5c69af212a15fe362711162b2e00b82f0e0588fb8259ecd9a70c5490562bf51d408b0cb92f277ead71a2390ddddfe7283b35d languageName: node linkType: hard -"@babel/core@npm:^7.0.0, @babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.23.9, @babel/core@npm:^7.27.4": - version: 7.28.5 - resolution: "@babel/core@npm:7.28.5" - dependencies: - "@babel/code-frame": ^7.27.1 - "@babel/generator": ^7.28.5 - "@babel/helper-compilation-targets": ^7.27.2 - "@babel/helper-module-transforms": ^7.28.3 - "@babel/helpers": ^7.28.4 - "@babel/parser": ^7.28.5 - "@babel/template": ^7.27.2 - "@babel/traverse": ^7.28.5 - "@babel/types": ^7.28.5 - "@jridgewell/remapping": ^2.3.5 - convert-source-map: ^2.0.0 - debug: ^4.1.0 - gensync: ^1.0.0-beta.2 - json5: ^2.2.3 - semver: ^6.3.1 - checksum: 1ee35b20448f73e9d531091ad4f9e8198dc8f0cebb783263fbff1807342209882ddcaf419be04111326b6f0e494222f7055d71da316c437a6a784d230c11ab9f - languageName: node - linkType: hard - -"@babel/core@npm:^7.29.7": +"@babel/core@npm:^7.0.0, @babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.23.9, @babel/core@npm:^7.27.4, @babel/core@npm:^7.29.7": version: 7.29.7 resolution: "@babel/core@npm:7.29.7" dependencies: @@ -121,20 +73,7 @@ __metadata: languageName: node linkType: hard -"@babel/generator@npm:^7.27.5, @babel/generator@npm:^7.28.5": - version: 7.28.5 - resolution: "@babel/generator@npm:7.28.5" - dependencies: - "@babel/parser": ^7.28.5 - "@babel/types": ^7.28.5 - "@jridgewell/gen-mapping": ^0.3.12 - "@jridgewell/trace-mapping": ^0.3.28 - jsesc: ^3.0.2 - checksum: 3e86fa0197bb33394a85a73dbbca92bb1b3f250a30294c7e327359c0978ad90f36f3d71c7f2965a3fc349cfa82becc8f87e7421c75796c8bc48dd9010dd866d1 - languageName: node - linkType: hard - -"@babel/generator@npm:^7.29.7": +"@babel/generator@npm:^7.27.5, @babel/generator@npm:^7.29.7": version: 7.29.7 resolution: "@babel/generator@npm:7.29.7" dependencies: @@ -147,15 +86,6 @@ __metadata: languageName: node linkType: hard -"@babel/helper-annotate-as-pure@npm:^7.27.1, @babel/helper-annotate-as-pure@npm:^7.27.3": - version: 7.27.3 - resolution: "@babel/helper-annotate-as-pure@npm:7.27.3" - dependencies: - "@babel/types": ^7.27.3 - checksum: 63863a5c936ef82b546ca289c9d1b18fabfc24da5c4ee382830b124e2e79b68d626207febc8d4bffc720f50b2ee65691d7d12cc0308679dee2cd6bdc926b7190 - languageName: node - linkType: hard - "@babel/helper-annotate-as-pure@npm:^7.29.7": version: 7.29.7 resolution: "@babel/helper-annotate-as-pure@npm:7.29.7" @@ -165,33 +95,7 @@ __metadata: languageName: node linkType: hard -"@babel/helper-compilation-targets@npm:^7.27.2": - version: 7.27.2 - resolution: "@babel/helper-compilation-targets@npm:7.27.2" - dependencies: - "@babel/compat-data": ^7.27.2 - "@babel/helper-validator-option": ^7.27.1 - browserslist: ^4.24.0 - lru-cache: ^5.1.1 - semver: ^6.3.1 - checksum: 7b95328237de85d7af1dea010a4daa28e79f961dda48b652860d5893ce9b136fc8b9ea1f126d8e0a24963b09ba5c6631dcb907b4ce109b04452d34a6ae979807 - languageName: node - linkType: hard - -"@babel/helper-compilation-targets@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/helper-compilation-targets@npm:7.28.6" - dependencies: - "@babel/compat-data": ^7.28.6 - "@babel/helper-validator-option": ^7.27.1 - browserslist: ^4.24.0 - lru-cache: ^5.1.1 - semver: ^6.3.1 - checksum: 8151e36b74eb1c5e414fe945c189436421f7bfa011884de5be3dd7fd77f12f1f733ff7c982581dfa0a49d8af724450243c2409427114b4a6cfeb8333259d001c - languageName: node - linkType: hard - -"@babel/helper-compilation-targets@npm:^7.29.7": +"@babel/helper-compilation-targets@npm:^7.28.6, @babel/helper-compilation-targets@npm:^7.29.7": version: 7.29.7 resolution: "@babel/helper-compilation-targets@npm:7.29.7" dependencies: @@ -204,24 +108,7 @@ __metadata: languageName: node linkType: hard -"@babel/helper-create-class-features-plugin@npm:^7.18.6": - version: 7.28.3 - resolution: "@babel/helper-create-class-features-plugin@npm:7.28.3" - dependencies: - "@babel/helper-annotate-as-pure": ^7.27.3 - "@babel/helper-member-expression-to-functions": ^7.27.1 - "@babel/helper-optimise-call-expression": ^7.27.1 - "@babel/helper-replace-supers": ^7.27.1 - "@babel/helper-skip-transparent-expression-wrappers": ^7.27.1 - "@babel/traverse": ^7.28.3 - semver: ^6.3.1 - peerDependencies: - "@babel/core": ^7.0.0 - checksum: 6d918e5e9c88ad1a262ab7b1a3caede1bbf95f8276c96846d8b0c1af251c85a0c868a9f1bbbaebdeb199e44dfd0e10fbe22935e56bedd1aa41ba4a7162bfa86c - languageName: node - linkType: hard - -"@babel/helper-create-class-features-plugin@npm:^7.29.7": +"@babel/helper-create-class-features-plugin@npm:^7.18.6, @babel/helper-create-class-features-plugin@npm:^7.29.7": version: 7.29.7 resolution: "@babel/helper-create-class-features-plugin@npm:7.29.7" dependencies: @@ -238,20 +125,7 @@ __metadata: languageName: node linkType: hard -"@babel/helper-create-regexp-features-plugin@npm:^7.18.6": - version: 7.27.1 - resolution: "@babel/helper-create-regexp-features-plugin@npm:7.27.1" - dependencies: - "@babel/helper-annotate-as-pure": ^7.27.1 - regexpu-core: ^6.2.0 - semver: ^6.3.1 - peerDependencies: - "@babel/core": ^7.0.0 - checksum: 2ede6bbad0016a9262fd281ce8f1a5d69e6179dcec4ea282830e924c29a29b66b0544ecb92e4ef4acdaf2c4c990931d7dc442dbcd6a8bcec4bad73923ef70934 - languageName: node - linkType: hard - -"@babel/helper-create-regexp-features-plugin@npm:^7.29.7": +"@babel/helper-create-regexp-features-plugin@npm:^7.18.6, @babel/helper-create-regexp-features-plugin@npm:^7.29.7": version: 7.29.7 resolution: "@babel/helper-create-regexp-features-plugin@npm:7.29.7" dependencies: @@ -279,13 +153,6 @@ __metadata: languageName: node linkType: hard -"@babel/helper-globals@npm:^7.28.0": - version: 7.28.0 - resolution: "@babel/helper-globals@npm:7.28.0" - checksum: d8d7b91c12dad1ee747968af0cb73baf91053b2bcf78634da2c2c4991fb45ede9bd0c8f9b5f3254881242bc0921218fcb7c28ae885477c25177147e978ce4397 - languageName: node - linkType: hard - "@babel/helper-globals@npm:^7.29.7": version: 7.29.7 resolution: "@babel/helper-globals@npm:7.29.7" @@ -293,16 +160,6 @@ __metadata: languageName: node linkType: hard -"@babel/helper-member-expression-to-functions@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/helper-member-expression-to-functions@npm:7.27.1" - dependencies: - "@babel/traverse": ^7.27.1 - "@babel/types": ^7.27.1 - checksum: b13a3d120015a6fd2f6e6c2ff789cd12498745ef028710cba612cfb751b91ace700c3f96c1689228d1dcb41e9d4cf83d6dff8627dcb0c8da12d79440e783c6b8 - languageName: node - linkType: hard - "@babel/helper-member-expression-to-functions@npm:^7.29.7": version: 7.29.7 resolution: "@babel/helper-member-expression-to-functions@npm:7.29.7" @@ -313,17 +170,7 @@ __metadata: languageName: node linkType: hard -"@babel/helper-module-imports@npm:^7.16.7, @babel/helper-module-imports@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/helper-module-imports@npm:7.27.1" - dependencies: - "@babel/traverse": ^7.27.1 - "@babel/types": ^7.27.1 - checksum: 92d01c71c0e4aacdc2babce418a9a1a27a8f7d770a210ffa0f3933f321befab18b655bc1241bebc40767516731de0b85639140c42e45a8210abe1e792f115b28 - languageName: node - linkType: hard - -"@babel/helper-module-imports@npm:^7.29.7": +"@babel/helper-module-imports@npm:^7.16.7, @babel/helper-module-imports@npm:^7.29.7": version: 7.29.7 resolution: "@babel/helper-module-imports@npm:7.29.7" dependencies: @@ -333,19 +180,6 @@ __metadata: languageName: node linkType: hard -"@babel/helper-module-transforms@npm:^7.28.3": - version: 7.28.3 - resolution: "@babel/helper-module-transforms@npm:7.28.3" - dependencies: - "@babel/helper-module-imports": ^7.27.1 - "@babel/helper-validator-identifier": ^7.27.1 - "@babel/traverse": ^7.28.3 - peerDependencies: - "@babel/core": ^7.0.0 - checksum: 7cf7b79da0fa626d6c84bfc7b35c079a2559caecaa2ff645b0f1db0d741507aa4df6b5b98a3283e8ac4e89094af271d805bf5701e5c4f916e622797b7c8cbb18 - languageName: node - linkType: hard - "@babel/helper-module-transforms@npm:^7.29.7": version: 7.29.7 resolution: "@babel/helper-module-transforms@npm:7.29.7" @@ -359,15 +193,6 @@ __metadata: languageName: node linkType: hard -"@babel/helper-optimise-call-expression@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/helper-optimise-call-expression@npm:7.27.1" - dependencies: - "@babel/types": ^7.27.1 - checksum: 0fb7ee824a384529d6b74f8a58279f9b56bfe3cce332168067dddeab2552d8eeb56dc8eaf86c04a3a09166a316cb92dfc79c4c623cd034ad4c563952c98b464f - languageName: node - linkType: hard - "@babel/helper-optimise-call-expression@npm:^7.29.7": version: 7.29.7 resolution: "@babel/helper-optimise-call-expression@npm:7.29.7" @@ -377,21 +202,7 @@ __metadata: languageName: node linkType: hard -"@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.10.4, @babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.14.5, @babel/helper-plugin-utils@npm:^7.18.6, @babel/helper-plugin-utils@npm:^7.27.1, @babel/helper-plugin-utils@npm:^7.8.0": - version: 7.27.1 - resolution: "@babel/helper-plugin-utils@npm:7.27.1" - checksum: 5d715055301badab62bdb2336075a77f8dc8bd290cad2bc1b37ea3bf1b3efc40594d308082229f239deb4d6b5b80b0a73bce000e595ea74416e0339c11037047 - languageName: node - linkType: hard - -"@babel/helper-plugin-utils@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/helper-plugin-utils@npm:7.28.6" - checksum: a0b4caab5e2180b215faa4d141ceac9e82fad9d446b8023eaeb8d82a6e62024726675b07fe8e616dd12f34e2bb59747e8d57aa8adab3e0717d1b8d691b118379 - languageName: node - linkType: hard - -"@babel/helper-plugin-utils@npm:^7.29.7": +"@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.10.4, @babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.14.5, @babel/helper-plugin-utils@npm:^7.18.6, @babel/helper-plugin-utils@npm:^7.27.1, @babel/helper-plugin-utils@npm:^7.28.6, @babel/helper-plugin-utils@npm:^7.29.7, @babel/helper-plugin-utils@npm:^7.8.0": version: 7.29.7 resolution: "@babel/helper-plugin-utils@npm:7.29.7" checksum: b0a183abcc6670afa4861425fa428217d8ebadce062d5b43117919e8715f820080fd63bbfcf0e43c6e0e7d21a96b21f635c46dda80bdb0ce7e8a762ebee1d8d9 @@ -411,19 +222,6 @@ __metadata: languageName: node linkType: hard -"@babel/helper-replace-supers@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/helper-replace-supers@npm:7.27.1" - dependencies: - "@babel/helper-member-expression-to-functions": ^7.27.1 - "@babel/helper-optimise-call-expression": ^7.27.1 - "@babel/traverse": ^7.27.1 - peerDependencies: - "@babel/core": ^7.0.0 - checksum: 3690266c304f21008690ba68062f889a363583cabc13c3d033b94513953147af3e0a3fdb48fa1bb9fa3734b64e221fc65e5222ab70837f02321b7225f487c6ef - languageName: node - linkType: hard - "@babel/helper-replace-supers@npm:^7.29.7": version: 7.29.7 resolution: "@babel/helper-replace-supers@npm:7.29.7" @@ -437,16 +235,6 @@ __metadata: languageName: node linkType: hard -"@babel/helper-skip-transparent-expression-wrappers@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/helper-skip-transparent-expression-wrappers@npm:7.27.1" - dependencies: - "@babel/traverse": ^7.27.1 - "@babel/types": ^7.27.1 - checksum: 4f380c5d0e0769fa6942a468b0c2d7c8f0c438f941aaa88f785f8752c103631d0904c7b4e76207a3b0e6588b2dec376595370d92ca8f8f1b422c14a69aa146d4 - languageName: node - linkType: hard - "@babel/helper-skip-transparent-expression-wrappers@npm:^7.29.7": version: 7.29.7 resolution: "@babel/helper-skip-transparent-expression-wrappers@npm:7.29.7" @@ -457,13 +245,6 @@ __metadata: languageName: node linkType: hard -"@babel/helper-string-parser@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/helper-string-parser@npm:7.27.1" - checksum: 0a8464adc4b39b138aedcb443b09f4005d86207d7126e5e079177e05c3116107d856ec08282b365e9a79a9872f40f4092a6127f8d74c8a01c1ef789dacfc25d6 - languageName: node - linkType: hard - "@babel/helper-string-parser@npm:^7.29.7": version: 7.29.7 resolution: "@babel/helper-string-parser@npm:7.29.7" @@ -471,13 +252,6 @@ __metadata: languageName: node linkType: hard -"@babel/helper-validator-identifier@npm:^7.27.1, @babel/helper-validator-identifier@npm:^7.28.5": - version: 7.28.5 - resolution: "@babel/helper-validator-identifier@npm:7.28.5" - checksum: 5a251a6848e9712aea0338f659a1a3bd334d26219d5511164544ca8ec20774f098c3a6661e9da65a0d085c745c00bb62c8fada38a62f08fa1f8053bc0aeb57e4 - languageName: node - linkType: hard - "@babel/helper-validator-identifier@npm:^7.29.7": version: 7.29.7 resolution: "@babel/helper-validator-identifier@npm:7.29.7" @@ -485,13 +259,6 @@ __metadata: languageName: node linkType: hard -"@babel/helper-validator-option@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/helper-validator-option@npm:7.27.1" - checksum: db73e6a308092531c629ee5de7f0d04390835b21a263be2644276cb27da2384b64676cab9f22cd8d8dbd854c92b1d7d56fc8517cf0070c35d1c14a8c828b0903 - languageName: node - linkType: hard - "@babel/helper-validator-option@npm:^7.29.7": version: 7.29.7 resolution: "@babel/helper-validator-option@npm:7.29.7" @@ -510,16 +277,6 @@ __metadata: languageName: node linkType: hard -"@babel/helpers@npm:^7.28.4": - version: 7.28.4 - resolution: "@babel/helpers@npm:7.28.4" - dependencies: - "@babel/template": ^7.27.2 - "@babel/types": ^7.28.4 - checksum: a8706219e0bd60c18bbb8e010aa122e9b14e7e7e67c21cc101e6f1b5e79dcb9a18d674f655997f85daaf421aa138cf284710bb04371a2255a0a3137f097430b4 - languageName: node - linkType: hard - "@babel/helpers@npm:^7.29.7": version: 7.29.7 resolution: "@babel/helpers@npm:7.29.7" @@ -530,18 +287,7 @@ __metadata: languageName: node linkType: hard -"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.23.9, @babel/parser@npm:^7.27.2, @babel/parser@npm:^7.28.5": - version: 7.28.5 - resolution: "@babel/parser@npm:7.28.5" - dependencies: - "@babel/types": ^7.28.5 - bin: - parser: ./bin/babel-parser.js - checksum: 5c2456e3f26c70d4a3ce1a220b529a91a2df26c54a2894fd0dea2342699ea1067ffdda9f0715eeab61da46ff546fd5661bc70be6d8d11977cbe21f5f0478819a - languageName: node - linkType: hard - -"@babel/parser@npm:^7.29.7": +"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.23.9, @babel/parser@npm:^7.29.7": version: 7.29.7 resolution: "@babel/parser@npm:7.29.7" dependencies: @@ -699,18 +445,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-import-attributes@npm:^7.24.7": - version: 7.27.1 - resolution: "@babel/plugin-syntax-import-attributes@npm:7.27.1" - dependencies: - "@babel/helper-plugin-utils": ^7.27.1 - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 97973982fff1bbf86b3d1df13380567042887c50e2ae13a400d02a8ff2c9742a60a75e279bfb73019e1cd9710f04be5e6ab81f896e6678dcfcec8b135e8896cf - languageName: node - linkType: hard - -"@babel/plugin-syntax-import-attributes@npm:^7.29.7": +"@babel/plugin-syntax-import-attributes@npm:^7.24.7, @babel/plugin-syntax-import-attributes@npm:^7.29.7": version: 7.29.7 resolution: "@babel/plugin-syntax-import-attributes@npm:7.29.7" dependencies: @@ -743,18 +478,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-jsx@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-syntax-jsx@npm:7.27.1" - dependencies: - "@babel/helper-plugin-utils": ^7.27.1 - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: c6d1324cff286a369aa95d99b8abd21dd07821b5d3affd5fe7d6058c84cff9190743287826463ee57a7beecd10fa1e4bc99061df532ee14e188c1c8937b13e3a - languageName: node - linkType: hard - -"@babel/plugin-syntax-jsx@npm:^7.29.7": +"@babel/plugin-syntax-jsx@npm:^7.27.1, @babel/plugin-syntax-jsx@npm:^7.29.7": version: 7.29.7 resolution: "@babel/plugin-syntax-jsx@npm:7.29.7" dependencies: @@ -1636,32 +1360,14 @@ __metadata: languageName: node linkType: hard -"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.28.2, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.8.7": - version: 7.28.4 - resolution: "@babel/runtime@npm:7.28.4" - checksum: 934b0a0460f7d06637d93fcd1a44ac49adc33518d17253b5a0b55ff4cb90a45d8fe78bf034b448911dbec7aff2a90b918697559f78d21c99ff8dbadae9565b55 - languageName: node - linkType: hard - -"@babel/runtime@npm:^7.29.7": +"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.28.2, @babel/runtime@npm:^7.29.7, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.8.7": version: 7.29.7 resolution: "@babel/runtime@npm:7.29.7" checksum: bc311855c6dbf5356030979584ca0f8b6cee39fe058175b02e85a73e246fc76ae30248b0d40e70c2652101faeb43279468ed2d086a670673eb9783c1fee1df2b languageName: node linkType: hard -"@babel/template@npm:^7.27.2, @babel/template@npm:^7.3.3": - version: 7.27.2 - resolution: "@babel/template@npm:7.27.2" - dependencies: - "@babel/code-frame": ^7.27.1 - "@babel/parser": ^7.27.2 - "@babel/types": ^7.27.1 - checksum: ff5628bc066060624afd970616090e5bba91c6240c2e4b458d13267a523572cbfcbf549391eec8217b94b064cf96571c6273f0c04b28a8567b96edc675c28e27 - languageName: node - linkType: hard - -"@babel/template@npm:^7.29.7": +"@babel/template@npm:^7.29.7, @babel/template@npm:^7.3.3": version: 7.29.7 resolution: "@babel/template@npm:7.29.7" dependencies: @@ -1672,21 +1378,6 @@ __metadata: languageName: node linkType: hard -"@babel/traverse@npm:^7.27.1, @babel/traverse@npm:^7.28.3, @babel/traverse@npm:^7.28.5": - version: 7.28.5 - resolution: "@babel/traverse@npm:7.28.5" - dependencies: - "@babel/code-frame": ^7.27.1 - "@babel/generator": ^7.28.5 - "@babel/helper-globals": ^7.28.0 - "@babel/parser": ^7.28.5 - "@babel/template": ^7.27.2 - "@babel/types": ^7.28.5 - debug: ^4.3.1 - checksum: e028ee9654f44be7c2a2df268455cee72d5c424c9ae536785f8f7c8680356f7b977c77ad76909d07eeed09ff1e125ce01cf783011f66b56c838791a85fa6af04 - languageName: node - linkType: hard - "@babel/traverse@npm:^7.29.7": version: 7.29.7 resolution: "@babel/traverse@npm:7.29.7" @@ -1702,17 +1393,7 @@ __metadata: languageName: node linkType: hard -"@babel/types@npm:^7.0.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.27.1, @babel/types@npm:^7.27.3, @babel/types@npm:^7.28.2, @babel/types@npm:^7.28.4, @babel/types@npm:^7.28.5, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4": - version: 7.28.5 - resolution: "@babel/types@npm:7.28.5" - dependencies: - "@babel/helper-string-parser": ^7.27.1 - "@babel/helper-validator-identifier": ^7.28.5 - checksum: 5bc266af9e55ff92f9ddf33d83a42c9de1a87f9579d0ed62ef94a741a081692dd410a4fbbab18d514b83e135083ff05bc0e37003834801c9514b9d8ad748070d - languageName: node - linkType: hard - -"@babel/types@npm:^7.29.7": +"@babel/types@npm:^7.0.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.27.3, @babel/types@npm:^7.28.2, @babel/types@npm:^7.29.7, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4": version: 7.29.7 resolution: "@babel/types@npm:7.29.7" dependencies: @@ -3737,17 +3418,7 @@ __metadata: languageName: node linkType: hard -"@types/send@npm:*": - version: 0.17.5 - resolution: "@types/send@npm:0.17.5" - dependencies: - "@types/mime": ^1 - "@types/node": "*" - checksum: bff5add75eb178c3b80bebc422db483c76eeb2cb5016508c952e4fc67d968794f9c709b978d086bf60e4d6fbfe8c0b77e99a7603a615c671c1f97f808458d4a8 - languageName: node - linkType: hard - -"@types/send@npm:<1": +"@types/send@npm:*, @types/send@npm:<1": version: 0.17.6 resolution: "@types/send@npm:0.17.6" dependencies: @@ -3766,18 +3437,7 @@ __metadata: languageName: node linkType: hard -"@types/serve-static@npm:*, @types/serve-static@npm:^1.15.5": - version: 1.15.8 - resolution: "@types/serve-static@npm:1.15.8" - dependencies: - "@types/http-errors": "*" - "@types/node": "*" - "@types/send": "*" - checksum: 41e0fb40bfdf3b5c2ac997c5dd5d58af9229e6a325dab1cf5f73b488b09635d933c1aa6f0e3265d6df8b45be0d09af36a9ffe90175088726f1db6bf104bf9ecf - languageName: node - linkType: hard - -"@types/serve-static@npm:^1": +"@types/serve-static@npm:*, @types/serve-static@npm:^1, @types/serve-static@npm:^1.15.5": version: 1.15.10 resolution: "@types/serve-static@npm:1.15.10" dependencies: @@ -4234,16 +3894,7 @@ __metadata: languageName: node linkType: hard -"acorn@npm:^8.14.0, acorn@npm:^8.15.0": - version: 8.15.0 - resolution: "acorn@npm:8.15.0" - bin: - acorn: bin/acorn - checksum: 309c6b49aedf1a2e34aaf266de06de04aab6eb097c02375c66fdeb0f64556a6a823540409914fb364d9a11bc30d79d485a2eba29af47992d3490e9886c4391c3 - languageName: node - linkType: hard - -"acorn@npm:^8.16.0": +"acorn@npm:^8.14.0, acorn@npm:^8.15.0, acorn@npm:^8.16.0": version: 8.16.0 resolution: "acorn@npm:8.16.0" bin: @@ -4388,13 +4039,6 @@ __metadata: languageName: node linkType: hard -"ansi-regex@npm:^6.0.1": - version: 6.2.0 - resolution: "ansi-regex@npm:6.2.0" - checksum: f1a540a85647187f21918a87ea3fc910adc6ecc2bfc180c22d9b01a04379dce3a6c1f2e5375ab78e8d7d589eb1aeb734f49171e262e90c4225f21b4415c08c8c - languageName: node - linkType: hard - "ansi-regex@npm:^6.2.2": version: 6.2.2 resolution: "ansi-regex@npm:6.2.2" @@ -7341,14 +6985,7 @@ __metadata: languageName: node linkType: hard -"get-east-asian-width@npm:^1.0.0, get-east-asian-width@npm:^1.3.0, get-east-asian-width@npm:^1.3.1": - version: 1.4.0 - resolution: "get-east-asian-width@npm:1.4.0" - checksum: 1d9a81a8004f4217ebef5d461875047d269e4b57e039558fd65130877cd4da8e3f61e1c4eada0c8b10e2816c7baf7d5fddb7006f561da13bc6f6dd19c1e964a4 - languageName: node - linkType: hard - -"get-east-asian-width@npm:^1.5.0": +"get-east-asian-width@npm:^1.0.0, get-east-asian-width@npm:^1.3.1, get-east-asian-width@npm:^1.5.0": version: 1.5.0 resolution: "get-east-asian-width@npm:1.5.0" checksum: 60bc34cd1e975055ab99f0f177e31bed3e516ff7cee9c536474383954a976abaa6b94a51d99ad158ef1e372790fa096cab7d07f166bb0778f6587954c0fbe946 @@ -7672,16 +7309,7 @@ __metadata: languageName: node linkType: hard -"hashery@npm:^1.2.0": - version: 1.3.0 - resolution: "hashery@npm:1.3.0" - dependencies: - hookified: ^1.13.0 - checksum: 88b2e605ce2614f0744eb68863986091fb697c8bdf54dadb13379d8630dcca246f5f7dac26945a781daeacc29321291788db0908b60f05944574222cd9eb4495 - languageName: node - linkType: hard - -"hashery@npm:^1.3.0": +"hashery@npm:^1.2.0, hashery@npm:^1.3.0": version: 1.4.0 resolution: "hashery@npm:1.4.0" dependencies: @@ -7708,14 +7336,7 @@ __metadata: languageName: node linkType: hard -"hookified@npm:^1.13.0": - version: 1.14.0 - resolution: "hookified@npm:1.14.0" - checksum: 343aa04df5bcd5308c86bfc8d60fe1e83b50d12f8444da609a5b5bf2661970d93a9103ec07b4d474e0285b95266cf02ebdf4efa5ede128974c97ae97befcef82 - languageName: node - linkType: hard - -"hookified@npm:^1.14.0, hookified@npm:^1.15.0": +"hookified@npm:^1.13.0, hookified@npm:^1.14.0, hookified@npm:^1.15.0": version: 1.15.1 resolution: "hookified@npm:1.15.1" checksum: ab3a009002b10a9cc4268f693b7b5a81bf22d188b3c3c08a8439538de090e1237744affdb96a26b58bb2a9068b2eee52c9d7ddd33848a5eef042aa28243b3a40 @@ -8170,7 +7791,7 @@ __metadata: languageName: node linkType: hard -"is-core-module@npm:^2.13.0, is-core-module@npm:^2.16.0, is-core-module@npm:^2.16.1": +"is-core-module@npm:^2.13.0, is-core-module@npm:^2.16.1": version: 2.16.1 resolution: "is-core-module@npm:2.16.1" dependencies: @@ -9241,15 +8862,6 @@ __metadata: languageName: node linkType: hard -"jsesc@npm:~3.0.2": - version: 3.0.2 - resolution: "jsesc@npm:3.0.2" - bin: - jsesc: bin/jsesc - checksum: a36d3ca40574a974d9c2063bf68c2b6141c20da8f2a36bd3279fc802563f35f0527a6c828801295bdfb2803952cf2cf387786c2c90ed564f88d5782475abfe3c - languageName: node - linkType: hard - "json-buffer@npm:3.0.1": version: 3.0.1 resolution: "json-buffer@npm:3.0.1" @@ -9561,14 +9173,7 @@ __metadata: languageName: node linkType: hard -"lodash@npm:^4.17.21": - version: 4.17.21 - resolution: "lodash@npm:4.17.21" - checksum: eb835a2e51d381e561e508ce932ea50a8e5a68f4ebdd771ea240d3048244a8d13658acbd502cd4829768c56f2e16bdd4340b9ea141297d472517b83868e677f7 - languageName: node - linkType: hard - -"lodash@npm:^4.18.1": +"lodash@npm:^4.17.21, lodash@npm:^4.18.1": version: 4.18.1 resolution: "lodash@npm:4.18.1" checksum: bb5f5b49aad29614e709af02b64c56b0f8b78c6a81434a3c1ae527d2f0f78ca08f9d9fb22aa825a053876c9d2166e9c01f31c356014b5e2bdc0556c057433102 @@ -9987,16 +9592,7 @@ __metadata: languageName: node linkType: hard -"minizlib@npm:^3.0.1": - version: 3.0.2 - resolution: "minizlib@npm:3.0.2" - dependencies: - minipass: ^7.1.2 - checksum: 493bed14dcb6118da7f8af356a8947cf1473289c09658e5aabd69a737800a8c3b1736fb7d7931b722268a9c9bc038a6d53c049b6a6af24b34a121823bb709996 - languageName: node - linkType: hard - -"minizlib@npm:^3.1.0": +"minizlib@npm:^3.0.1, minizlib@npm:^3.1.0": version: 3.1.0 resolution: "minizlib@npm:3.1.0" dependencies: @@ -10801,17 +10397,7 @@ __metadata: languageName: node linkType: hard -"postcss-selector-parser@npm:^7.0.0": - version: 7.1.0 - resolution: "postcss-selector-parser@npm:7.1.0" - dependencies: - cssesc: ^3.0.0 - util-deprecate: ^1.0.2 - checksum: 1300e7871dd60a5132ee5462cc6e94edd4f3df28462b2495ca9ff025bd83768a908e892a18fde62cae63ff63524641baa6d58c64120f04fe6884b916663ce737 - languageName: node - linkType: hard - -"postcss-selector-parser@npm:^7.1.1": +"postcss-selector-parser@npm:^7.0.0, postcss-selector-parser@npm:^7.1.1": version: 7.1.1 resolution: "postcss-selector-parser@npm:7.1.1" dependencies: @@ -10828,18 +10414,7 @@ __metadata: languageName: node linkType: hard -"postcss@npm:^8.4.40, postcss@npm:^8.5.6": - version: 8.5.6 - resolution: "postcss@npm:8.5.6" - dependencies: - nanoid: ^3.3.11 - picocolors: ^1.1.1 - source-map-js: ^1.2.1 - checksum: 20f3b5d673ffeec2b28d65436756d31ee33f65b0a8bedb3d32f556fbd5973be38c3a7fb5b959a5236c60a5db7b91b0a6b14ffaac0d717dce1b903b964ee1c1bb - languageName: node - linkType: hard - -"postcss@npm:^8.5.10": +"postcss@npm:^8.4.40, postcss@npm:^8.5.10, postcss@npm:^8.5.6": version: 8.5.14 resolution: "postcss@npm:8.5.14" dependencies: @@ -11307,15 +10882,6 @@ __metadata: languageName: node linkType: hard -"regenerate-unicode-properties@npm:^10.2.0": - version: 10.2.0 - resolution: "regenerate-unicode-properties@npm:10.2.0" - dependencies: - regenerate: ^1.4.2 - checksum: d5c5fc13f8b8d7e16e791637a4bfef741f8d70e267d51845ee7d5404a32fa14c75b181c4efba33e4bff8b0000a2f13e9773593713dfe5b66597df4259275ce63 - languageName: node - linkType: hard - "regenerate-unicode-properties@npm:^10.2.2": version: 10.2.2 resolution: "regenerate-unicode-properties@npm:10.2.2" @@ -11346,20 +10912,6 @@ __metadata: languageName: node linkType: hard -"regexpu-core@npm:^6.2.0": - version: 6.2.0 - resolution: "regexpu-core@npm:6.2.0" - dependencies: - regenerate: ^1.4.2 - regenerate-unicode-properties: ^10.2.0 - regjsgen: ^0.8.0 - regjsparser: ^0.12.0 - unicode-match-property-ecmascript: ^2.0.0 - unicode-match-property-value-ecmascript: ^2.1.0 - checksum: 67d3c4a3f6c99bc80b5d690074a27e6f675be1c1739f8a9acf028fbc36f1a468472574ea65e331e217995198ba4404d7878f3cb3739a73552dd3c70d3fb7f8e6 - languageName: node - linkType: hard - "regexpu-core@npm:^6.3.1": version: 6.4.0 resolution: "regexpu-core@npm:6.4.0" @@ -11381,17 +10933,6 @@ __metadata: languageName: node linkType: hard -"regjsparser@npm:^0.12.0": - version: 0.12.0 - resolution: "regjsparser@npm:0.12.0" - dependencies: - jsesc: ~3.0.2 - bin: - regjsparser: bin/parser - checksum: 094b55b0ab3e1fd58f8ce5132a1d44dab08d91f7b0eea4132b0157b303ebb8ded20a9cbd893d25402d2aeddb23fac1f428ab4947b295d6fa51dd1c334a9e76f0 - languageName: node - linkType: hard - "regjsparser@npm:^0.13.0": version: 0.13.0 resolution: "regjsparser@npm:0.13.0" @@ -11463,20 +11004,7 @@ __metadata: languageName: node linkType: hard -"resolve@npm:^1.19.0, resolve@npm:^1.20.0": - version: 1.22.10 - resolution: "resolve@npm:1.22.10" - dependencies: - is-core-module: ^2.16.0 - path-parse: ^1.0.7 - supports-preserve-symlinks-flag: ^1.0.0 - bin: - resolve: bin/resolve - checksum: ab7a32ff4046fcd7c6fdd525b24a7527847d03c3650c733b909b01b757f92eb23510afa9cc3e9bf3f26a3e073b48c88c706dfd4c1d2fb4a16a96b73b6328ddcf - languageName: node - linkType: hard - -"resolve@npm:^1.22.11": +"resolve@npm:^1.19.0, resolve@npm:^1.20.0, resolve@npm:^1.22.11": version: 1.22.11 resolution: "resolve@npm:1.22.11" dependencies: @@ -11502,20 +11030,7 @@ __metadata: languageName: node linkType: hard -"resolve@patch:resolve@^1.19.0#~builtin, resolve@patch:resolve@^1.20.0#~builtin": - version: 1.22.10 - resolution: "resolve@patch:resolve@npm%3A1.22.10#~builtin::version=1.22.10&hash=c3c19d" - dependencies: - is-core-module: ^2.16.0 - path-parse: ^1.0.7 - supports-preserve-symlinks-flag: ^1.0.0 - bin: - resolve: bin/resolve - checksum: 8aac1e4e4628bd00bf4b94b23de137dd3fe44097a8d528fd66db74484be929936e20c696e1a3edf4488f37e14180b73df6f600992baea3e089e8674291f16c9d - languageName: node - linkType: hard - -"resolve@patch:resolve@^1.22.11#~builtin": +"resolve@patch:resolve@^1.19.0#~builtin, resolve@patch:resolve@^1.20.0#~builtin, resolve@patch:resolve@^1.22.11#~builtin": version: 1.22.11 resolution: "resolve@patch:resolve@npm%3A1.22.11#~builtin::version=1.22.11&hash=c3c19d" dependencies: @@ -11783,16 +11298,7 @@ __metadata: languageName: node linkType: hard -"semver@npm:^7.3.5, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.7.2": - version: 7.7.2 - resolution: "semver@npm:7.7.2" - bin: - semver: bin/semver.js - checksum: dd94ba8f1cbc903d8eeb4dd8bf19f46b3deb14262b6717d0de3c804b594058ae785ef2e4b46c5c3b58733c99c83339068203002f9e37cfe44f7e2cc5e3d2f621 - languageName: node - linkType: hard - -"semver@npm:^7.6.3": +"semver@npm:^7.3.5, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.6.3, semver@npm:^7.7.2": version: 7.7.4 resolution: "semver@npm:7.7.4" bin: @@ -12292,17 +11798,7 @@ __metadata: languageName: node linkType: hard -"string-width@npm:^8.0.0": - version: 8.1.0 - resolution: "string-width@npm:8.1.0" - dependencies: - get-east-asian-width: ^1.3.0 - strip-ansi: ^7.1.0 - checksum: 51ee97c4ffee7b94f8a2ee785fac14f81ec9809b9fcec9a4db44e25c717c263af0cc4387c111aef76195c0718dc43766f3678c07fb542294fb0244f7bfbde883 - languageName: node - linkType: hard - -"string-width@npm:^8.1.1": +"string-width@npm:^8.0.0, string-width@npm:^8.1.1": version: 8.2.0 resolution: "string-width@npm:8.2.0" dependencies: @@ -12408,16 +11904,7 @@ __metadata: languageName: node linkType: hard -"strip-ansi@npm:^7.0.1, strip-ansi@npm:^7.1.0": - version: 7.1.2 - resolution: "strip-ansi@npm:7.1.2" - dependencies: - ansi-regex: ^6.0.1 - checksum: db0e3f9654e519c8a33c50fc9304d07df5649388e7da06d3aabf66d29e5ad65d5e6315d8519d409c15b32fa82c1df7e11ed6f8cd50b0e4404463f0c9d77c8d0b - languageName: node - linkType: hard - -"strip-ansi@npm:^7.1.2": +"strip-ansi@npm:^7.0.1, strip-ansi@npm:^7.1.0, strip-ansi@npm:^7.1.2": version: 7.2.0 resolution: "strip-ansi@npm:7.2.0" dependencies: @@ -12653,7 +12140,7 @@ __metadata: languageName: node linkType: hard -"synckit@npm:^0.11.12": +"synckit@npm:^0.11.12, synckit@npm:^0.11.8": version: 0.11.12 resolution: "synckit@npm:0.11.12" dependencies: @@ -12662,15 +12149,6 @@ __metadata: languageName: node linkType: hard -"synckit@npm:^0.11.8": - version: 0.11.11 - resolution: "synckit@npm:0.11.11" - dependencies: - "@pkgr/core": ^0.2.9 - checksum: bc896d4320525501495654766e6b0aa394e522476ea0547af603bdd9fd7e9b65dcd6e3a237bc7eb3ab7e196376712f228bf1bf6ed1e1809f4b32dc9baf7ad413 - languageName: node - linkType: hard - "table@npm:^6.9.0": version: 6.9.0 resolution: "table@npm:6.9.0" @@ -13061,13 +12539,6 @@ __metadata: languageName: node linkType: hard -"unicode-match-property-value-ecmascript@npm:^2.1.0": - version: 2.2.0 - resolution: "unicode-match-property-value-ecmascript@npm:2.2.0" - checksum: 9e3151e1d0bc6be35c4cef105e317c04090364173e8462005b5cde08a1e7c858b6586486cfebac39dc2c6c8c9ee24afb245de6d527604866edfa454fe2a35fae - languageName: node - linkType: hard - "unicode-match-property-value-ecmascript@npm:^2.2.1": version: 2.2.1 resolution: "unicode-match-property-value-ecmascript@npm:2.2.1" From fd7c78c6301ab8ae037fcd3e69c838f5e630963c Mon Sep 17 00:00:00 2001 From: Jason De Lanerolle Date: Tue, 9 Jun 2026 12:09:41 -0400 Subject: [PATCH 19/39] Update backend wiring --- app/Controllers/Timetable.hs | 30 +++++++++++++++--------------- app/Database/Tables.hs | 31 +++++++++++++++---------------- 2 files changed, 30 insertions(+), 31 deletions(-) diff --git a/app/Controllers/Timetable.hs b/app/Controllers/Timetable.hs index 9763698f4..6faa16021 100644 --- a/app/Controllers/Timetable.hs +++ b/app/Controllers/Timetable.hs @@ -45,11 +45,11 @@ gridResponse = -- | Returns an image of the timetable requested by the user. exportTimetableImageResponse :: ServerPart Response exportTimetableImageResponse = do - session <- lookText' "session" + selectedSession <- lookText' "session" selectedCourses <- lookText' "courses" liftIO $ withSystemTempDirectory "timetable-image" $ \tempDir -> do - pngPath <- getActiveTimetable selectedCourses session tempDir + pngPath <- getActiveTimetable selectedCourses selectedSession tempDir readImageData pngPath -- | Returns a PDF containing graph and timetable requested by the user. @@ -131,14 +131,14 @@ type Session = T.Text getCoursesInfo :: T.Text -> [(Code, Section, Session)] getCoursesInfo courses = map courseInfo allCourses where - courseInfo [code, sect, session] = (code, sect, session) + courseInfo [code, sect, sess] = (code, sect, sess) courseInfo _ = ("", "", "") allCourses = map (T.splitOn "-") (T.splitOn "_" courses) -- | Pulls either a Lecture, Tutorial or Pratical from the database. pullDatabase :: (Code, Section, Session) -> IO (Maybe MeetTime') -pullDatabase (code, section, session) = runDb $ do - meet <- returnMeeting code fullSection session +pullDatabase (code, sect, sess) = runDb $ do + meet <- returnMeeting code fullSection sess case meet of Nothing -> return Nothing Just x -> do @@ -147,11 +147,11 @@ pullDatabase (code, section, session) = runDb $ do return $ Just (MeetTime' (entityVal x) parsedTime) where fullSection - | T.isPrefixOf "L" section = T.append "LEC" sectCode - | T.isPrefixOf "T" section = T.append "TUT" sectCode - | T.isPrefixOf "P" section = T.append "PRA" sectCode - | otherwise = section - sectCode = T.tail section + | T.isPrefixOf "L" sect = T.append "LEC" sectCode + | T.isPrefixOf "T" sect = T.append "TUT" sectCode + | T.isPrefixOf "P" sect = T.append "PRA" sectCode + | otherwise = sect + sectCode = T.tail sect -- | The current date and time as obtained from the system. type SystemTime = String @@ -314,12 +314,12 @@ formatMinutes decimal = if minutes >= 10 then show minutes else '0' : show minut -- | Obtains all the dates for each course depending on its session. getDatesByCourse :: InfoTimeFieldsByDay -> Session -> IO DatesByDay -getDatesByCourse dataInOrder session - | session == "Y" = do +getDatesByCourse dataInOrder selectedSession + | selectedSession == "Y" = do fallDates <- mapM (getDatesByDay "F") dataInOrder winterDates <- mapM (getDatesByDay "S") dataInOrder return (fallDates ++ winterDates) - | otherwise = mapM (getDatesByDay session) dataInOrder + | otherwise = mapM (getDatesByDay selectedSession) dataInOrder -- | The string representation for a date in which an event -- occurs for the first time. @@ -333,8 +333,8 @@ type EndDate = String -- course takes place, depending on the course session. getDatesByDay :: Session -> [Time] -> IO (StartDate, EndDate) getDatesByDay _ [] = error "Failed to fetch dates" -getDatesByDay session (firstDate:_) - | session == "F" = do +getDatesByDay selectedSession (firstDate:_) + | selectedSession == "F" = do fallStart <- fallStartDate fallEnd <- fallEndDate formatDates $ getDates fallStart fallEnd dayOfWeek diff --git a/app/Database/Tables.hs b/app/Database/Tables.hs index 5bab8e3a5..f53896a33 100644 --- a/app/Database/Tables.hs +++ b/app/Database/Tables.hs @@ -169,19 +169,19 @@ data SvgJSON = } deriving (Show, Generic) data Time' = - Time' { weekDay' :: Double, + Time' { session' :: Maybe T.Text, + weekDay' :: Double, startHour' :: Double, endHour' :: Double, - firstLocation' :: Maybe T.Text, - secondLocation' :: Maybe T.Text + location' :: Maybe T.Text } deriving (Show, Generic) data Time = - Time { weekDay :: Double, + Time { session :: Maybe T.Text, + weekDay :: Double, startHour :: Double, endHour :: Double, - firstLocation :: Maybe Building, - secondLocation :: Maybe Building + location :: Maybe Building } deriving (Show, Generic) -- | A Meeting with its associated Times. @@ -256,12 +256,11 @@ instance FromJSON Time' where building <- o .: "building" buildingCode <- building .: "buildingCode" - buildingRoomNumber <- building .: "buildingRoomNumber" - let meetingRoom1 = Just (T.concat [buildingCode, buildingRoomNumber]) - meetingRoom2 <- o .:? "assignedRoom2" .!= Nothing + + session <- o .:? "sessionCode" let (adjustedDay, adjustedStartTime, adjustedEndTime) = convertTimeVals meetingDay meetingStartTime meetingEndTime - return $ Time' adjustedDay adjustedStartTime adjustedEndTime meetingRoom1 meetingRoom2 + return $ Time' session adjustedDay adjustedStartTime adjustedEndTime buildingCode instance FromJSON MeetTime where parseJSON (Object o) = do @@ -312,21 +311,21 @@ convertTimeVals _ _ _ = (5.0, 25.0, 25.0) -- | Convert Times into Time buildTime :: Times -> SqlPersistM Time buildTime t = do - room1 <- getBuilding (timesLocation t) - return $ Time (timesWeekDay t) + building <- getBuilding (timesLocation t) + return $ Time (timesSession t) + (timesWeekDay t) (timesStartHour t) (timesEndHour t) - room1 - Nothing -- Temporary null data + building buildTimes :: Key Meeting -> Time' -> Times buildTimes meetingKey t = - Times (Just "") -- Temporary null data + Times (session' t) (weekDay' t) (startHour' t) (endHour' t) meetingKey - (firstLocation' t) + (location' t) -- | Given a building code, get the persistent Building associated with it getBuilding :: Maybe T.Text -> SqlPersistM (Maybe Building) From 41298686e86c8d6873af0d32d506aa67ddc84733 Mon Sep 17 00:00:00 2001 From: Jason De Lanerolle Date: Tue, 9 Jun 2026 12:09:56 -0400 Subject: [PATCH 20/39] Update frontend wiring --- .../common/__tests__/GetTable.test.js | 45 ++++++----- js/components/common/react_modal.js.jsx | 50 +++--------- .../graph/__mocks__/aaa100-course-info.js | 76 +++++++++---------- .../graph/__mocks__/bbb100-course-info.js | 76 +++++++++---------- .../graph/__mocks__/ccc100-course-info.js | 76 +++++++++---------- js/components/grid/calendar.js.jsx | 4 +- 6 files changed, 147 insertions(+), 180 deletions(-) diff --git a/js/components/common/__tests__/GetTable.test.js b/js/components/common/__tests__/GetTable.test.js index a65f7a900..9808098af 100644 --- a/js/components/common/__tests__/GetTable.test.js +++ b/js/components/common/__tests__/GetTable.test.js @@ -25,7 +25,7 @@ describe("getTable", () => { timeData: [ { endHour: 17, - firstRoom: { + location: { buildingAddress: "80 St. George Street", buildingCode: "LM", buildingName: "Lash Miller Chemical Laboratories", @@ -33,7 +33,7 @@ describe("getTable", () => { buildingLng: -79.39841172598216, buildingPostalCode: "M5S 3H6", }, - secondRoom: null, + session: "F", startHour: 15, weekDay: 1, }, @@ -50,7 +50,7 @@ describe("getTable", () => { availability: "31 of 69 available", waitList: "0 students", time: ["Tuesday 15 - 17"], - location: ["LM "], + location: ["LM"], }, ] expect(actual).toEqual(expected) @@ -74,7 +74,7 @@ describe("getTable", () => { timeData: [ { endHour: 17, - firstRoom: { + location: { buildingAddress: "15 King's College Circle", buildingCode: "UC", buildingName: "University College", @@ -82,13 +82,13 @@ describe("getTable", () => { buildingLng: -79.395181775127, buildingPostalCode: "M5S 3H7", }, - secondRoom: null, + session: "F", startHour: 16, weekDay: 3, }, { endHour: 17, - firstRoom: { + location: { buildingAddress: "80 St. George Street", buildingCode: "LM", buildingName: "Lash Miller Chemical Laboratories", @@ -96,7 +96,7 @@ describe("getTable", () => { buildingLng: -79.39841172598216, buildingPostalCode: "M5S 3H6", }, - secondRoom: null, + session: "F", startHour: 15, weekDay: 1, }, @@ -113,7 +113,7 @@ describe("getTable", () => { availability: "31 of 69 available", waitList: "0 students", time: ["Tuesday 15 - 17", "Thursday 16 - 17"], - location: ["LM ", "UC "], + location: ["LM", "UC"], }, ] @@ -121,6 +121,9 @@ describe("getTable", () => { }) }) + /*** + * TODO: Re-implement this test once the logic for formatting Y courses is complete + describe("The occurence of the lecture has two locations ", () => { beforeEach(() => { meetingTime = [ @@ -177,6 +180,8 @@ describe("getTable", () => { }) }) + */ + describe("The meeting time has two lectures each with one occurence", () => { beforeEach(() => { meetingTime = [ @@ -194,7 +199,7 @@ describe("getTable", () => { timeData: [ { endHour: 17, - firstRoom: { + location: { buildingAddress: "80 St. George Street", buildingCode: "LM", buildingName: "Lash Miller Chemical Laboratories", @@ -202,7 +207,7 @@ describe("getTable", () => { buildingLng: -79.39841172598216, buildingPostalCode: "M5S 3H6", }, - secondRoom: null, + session: "F", startHour: 15, weekDay: 1, }, @@ -222,7 +227,7 @@ describe("getTable", () => { timeData: [ { endHour: 17, - firstRoom: { + location: { buildingAddress: "80 St. George Street", buildingCode: "LM", buildingName: "Lash Miller Chemical Laboratories", @@ -230,7 +235,7 @@ describe("getTable", () => { buildingLng: -79.39841172598216, buildingPostalCode: "M5S 3H6", }, - secondRoom: null, + session: "F", startHour: 15, weekDay: 1, }, @@ -247,7 +252,7 @@ describe("getTable", () => { availability: "31 of 69 available", waitList: "0 students", time: ["Tuesday 15 - 17"], - location: ["LM "], + location: ["LM"], }, { activity: "LEC2001", @@ -255,7 +260,7 @@ describe("getTable", () => { availability: "0 of 1 available", waitList: "0 students", time: ["Tuesday 15 - 17"], - location: ["LM "], + location: ["LM"], }, ] expect(actual).toEqual(expected) @@ -279,8 +284,8 @@ describe("getTable", () => { timeData: [ { endHour: 16, - firstRoom: null, - secondRoom: null, + location: null, + session: "F", startHour: 14, weekDay: 0, }, @@ -300,7 +305,7 @@ describe("getTable", () => { timeData: [ { endHour: 17, - firstRoom: { + location: { buildingAddress: "80 St. George Street", buildingCode: "LM", buildingName: "Lash Miller Chemical Laboratories", @@ -308,7 +313,7 @@ describe("getTable", () => { buildingLng: -79.39841172598216, buildingPostalCode: "M5S 3H6", }, - secondRoom: null, + session: "F", startHour: 15, weekDay: 1, }, @@ -325,7 +330,7 @@ describe("getTable", () => { availability: "31 of 69 available", waitList: "0 students", time: ["Tuesday 15 - 17"], - location: ["LM "], + location: ["LM"], }, { activity: "TUT0301", @@ -333,7 +338,7 @@ describe("getTable", () => { availability: "2 of 166 available", waitList: "0 students", time: ["Monday 14 - 16"], - location: [" "], + location: [" "], }, ] expect(actual).toEqual(expected) diff --git a/js/components/common/react_modal.js.jsx b/js/components/common/react_modal.js.jsx index 8a8ddd6ec..e857258d2 100644 --- a/js/components/common/react_modal.js.jsx +++ b/js/components/common/react_modal.js.jsx @@ -148,24 +148,11 @@ class CourseModal extends React.Component { occ1.weekDay > occ2.weekDay ? 1 : -1 ) sortedTimeData.map(occurrence => { - let firstRoom = "" - if (occurrence.firstRoom === null || occurrence.firstRoom === undefined) { - firstRoom = " " - } else { - firstRoom = occurrence.firstRoom.buildingCode + let location = " " + if (occurrence.location !== null && occurrence.location !== undefined) { + location = occurrence.location.buildingCode } - - let secondRoom = "" - if (occurrence.secondRoom === null || occurrence.secondRoom === undefined) { - secondRoom = " " - } else { - secondRoom = occurrence.secondRoom.buildingCode - } - - if ((firstRoom != " ") & (secondRoom != " ")) { - firstRoom += ", " - } - occurrences.locations.push(firstRoom + secondRoom) + occurrences.locations.push(location) occurrences.times.push( DAY_TO_INT[occurrence.weekDay] + " " + @@ -605,11 +592,8 @@ class MapModal extends React.Component { const lecturesByDay = {} this.props.lectures.forEach(lecture => { - if (lecture.fstLocation) { - this.groupLecturesByBuilding(lecturesByBuilding, lecture, "fstLocation") - } - if (lecture.secLocation) { - this.groupLecturesByBuilding(lecturesByBuilding, lecture, "secLocation") + if (lecture.location) { + this.groupLecturesByBuilding(lecturesByBuilding, lecture, "location") } if (lecturesByDay[lecture.dayString]) { @@ -691,18 +675,16 @@ class DayBox extends React.Component { } this.toggleExpand = this.toggleExpand.bind(this) - this.getLocationStr = this.getLocationStr.bind(this) + this.formatLocation = this.formatLocation.bind(this) } toggleExpand() { this.setState({ expanded: !this.state.expanded }) } - getLocationStr(lec, location, locationNum) { + formatLocation(location) { return ( - "Location" + - (lec.fstLocation && lec.secLocation ? " " + locationNum : "") + - ": " + + "Location: " + location.buildingName + " (" + location.buildingCode + @@ -750,15 +732,8 @@ class DayBox extends React.Component {
    {this.props.dayLectures.map(lec => { let locationStr = "" - let locationNum = 0 - if (lec.fstLocation) { - locationNum += 1 - locationStr += this.getLocationStr(lec, lec.fstLocation, locationNum) - } - if (lec.secLocation) { - locationNum += 1 - locationStr += - (lec.fstLocation ? "\n" : "") + this.getLocationStr(lec, lec.secLocation, locationNum) + if (lec.location) { + locationStr += this.formatLocation(lec.location) } return ( @@ -873,8 +848,7 @@ class CampusMap extends React.Component { let colouredMarker const buildingInd = this.props.selectedLecTimeframes.findIndex( lec => - (lec.fstLocation && lec.fstLocation.buildingCode === building.buildingCode) || - (lec.secLocation && lec.secLocation.buildingCode === building.buildingCode) + (lec.location && lec.location.buildingCode === building.buildingCode) ) colouredMarker = buildingInd == -1 ? blueMarker : redMarker diff --git a/js/components/graph/__mocks__/aaa100-course-info.js b/js/components/graph/__mocks__/aaa100-course-info.js index e49c19851..706d6c337 100644 --- a/js/components/graph/__mocks__/aaa100-course-info.js +++ b/js/components/graph/__mocks__/aaa100-course-info.js @@ -6,16 +6,16 @@ export default { timeData: [ { endingTime: 14, - secLocation: null, startingTime: 12, - fstLocation: "MY 150", + session: "F", + location: "MY 150", weekDay: 1, }, { endingTime: 14, - secLocation: null, startingTime: 13, - fstLocation: "MY 150", + session: "F", + location: "MY 150", weekDay: 3, }, ], @@ -34,16 +34,16 @@ export default { timeData: [ { endingTime: 15, - secLocation: null, startingTime: 13, - fstLocation: "BA 1160", + session: "F", + location: "BA 1160", weekDay: 2, }, { endingTime: 14, - secLocation: null, startingTime: 13, - fstLocation: "BA 1160", + session: "F", + location: "BA 1160", weekDay: 4, }, ], @@ -62,9 +62,9 @@ export default { timeData: [ { endingTime: 21, - secLocation: null, startingTime: 18, - fstLocation: "MY 150", + session: "F", + location: "MY 150", weekDay: 1, }, ], @@ -83,16 +83,16 @@ export default { timeData: [ { endingTime: 14, - secLocation: null, startingTime: 13, - fstLocation: "MY 150", + session: "F", + location: "MY 150", weekDay: 3, }, { endingTime: 14, - secLocation: null, startingTime: 12, - fstLocation: "MY 150", + session: "F", + location: "MY 150", weekDay: 1, }, ], @@ -111,9 +111,9 @@ export default { timeData: [ { endingTime: 21, - secLocation: null, startingTime: 18, - fstLocation: "MY 150", + session: "F", + location: "MY 150", weekDay: 1, }, ], @@ -132,9 +132,7 @@ export default { timeData: [ { endingTime: 25, - secLocation: null, startingTime: 25, - fstLocation: null, weekDay: 5, }, ], @@ -153,16 +151,16 @@ export default { timeData: [ { endingTime: 14, - secLocation: "MY 150", + session: "S", + location: "MY 150", startingTime: 13, - fstLocation: null, weekDay: 4, }, { endingTime: 15, - secLocation: "MY 150", + session: "S", + location: "MY 150", startingTime: 13, - fstLocation: null, weekDay: 1, }, ], @@ -194,9 +192,9 @@ export default { timeData: [ { endingTime: 17, - secLocation: "Contact Dept", + session: "S", + location: "Contact Dept", startingTime: 16, - fstLocation: null, weekDay: 0, }, ], @@ -215,9 +213,9 @@ export default { timeData: [ { endingTime: 16, - secLocation: "MY 315", + session: "S", + location: "MY 315", startingTime: 13, - fstLocation: null, weekDay: 3, }, ], @@ -236,9 +234,9 @@ export default { timeData: [ { endingTime: 21, - secLocation: "MY 150", + session: "S", + location: "MY 150", startingTime: 18, - fstLocation: null, weekDay: 1, }, ], @@ -257,16 +255,16 @@ export default { timeData: [ { endingTime: 15, - secLocation: "MY 150", + session: "S", + location: "MY 150", startingTime: 13, - fstLocation: null, weekDay: 1, }, { endingTime: 14, - secLocation: "MY 150", + session: "S", + location: "MY 150", startingTime: 13, - fstLocation: null, weekDay: 4, }, ], @@ -285,9 +283,9 @@ export default { timeData: [ { endingTime: 21, - secLocation: "MY 150", + session: "S", + location: "MY 150", startingTime: 18, - fstLocation: null, weekDay: 1, }, ], @@ -306,9 +304,9 @@ export default { timeData: [ { endingTime: 17, - secLocation: "Contact Dept", + session: "S", + location: "Contact Dept", startingTime: 16, - fstLocation: null, weekDay: 4, }, ], @@ -327,9 +325,7 @@ export default { timeData: [ { endingTime: 25, - secLocation: null, startingTime: 25, - fstLocation: null, weekDay: 5, }, ], @@ -348,9 +344,9 @@ export default { timeData: [ { endingTime: 17, - secLocation: "Contact Dept", + session: "S", + location: "Contact Dept", startingTime: 16, - fstLocation: null, weekDay: 2, }, ], diff --git a/js/components/graph/__mocks__/bbb100-course-info.js b/js/components/graph/__mocks__/bbb100-course-info.js index 28d8c52ea..e85c8a23d 100644 --- a/js/components/graph/__mocks__/bbb100-course-info.js +++ b/js/components/graph/__mocks__/bbb100-course-info.js @@ -6,16 +6,16 @@ export default { timeData: [ { endingTime: 14, - secLocation: null, startingTime: 12, - fstLocation: "MY 150", + session: "F", + location: "MY 150", weekDay: 1, }, { endingTime: 14, - secLocation: null, startingTime: 13, - fstLocation: "MY 150", + session: "F", + location: "MY 150", weekDay: 3, }, ], @@ -34,16 +34,16 @@ export default { timeData: [ { endingTime: 15, - secLocation: null, startingTime: 13, - fstLocation: "BA 1160", + session: "F", + location: "BA 1160", weekDay: 2, }, { endingTime: 14, - secLocation: null, startingTime: 13, - fstLocation: "BA 1160", + session: "F", + location: "BA 1160", weekDay: 4, }, ], @@ -62,9 +62,9 @@ export default { timeData: [ { endingTime: 21, - secLocation: null, startingTime: 18, - fstLocation: "MY 150", + session: "F", + location: "MY 150", weekDay: 1, }, ], @@ -83,16 +83,16 @@ export default { timeData: [ { endingTime: 14, - secLocation: null, startingTime: 13, - fstLocation: "MY 150", + session: "F", + location: "MY 150", weekDay: 3, }, { endingTime: 14, - secLocation: null, startingTime: 12, - fstLocation: "MY 150", + session: "F", + location: "MY 150", weekDay: 1, }, ], @@ -111,9 +111,9 @@ export default { timeData: [ { endingTime: 21, - secLocation: null, startingTime: 18, - fstLocation: "MY 150", + session: "F", + location: "MY 150", weekDay: 1, }, ], @@ -132,9 +132,7 @@ export default { timeData: [ { endingTime: 25, - secLocation: null, startingTime: 25, - fstLocation: null, weekDay: 5, }, ], @@ -153,16 +151,16 @@ export default { timeData: [ { endingTime: 14, - secLocation: "MY 150", + session: "S", + location: "MY 150", startingTime: 13, - fstLocation: null, weekDay: 4, }, { endingTime: 15, - secLocation: "MY 150", + session: "S", + location: "MY 150", startingTime: 13, - fstLocation: null, weekDay: 1, }, ], @@ -194,9 +192,9 @@ export default { timeData: [ { endingTime: 17, - secLocation: "Contact Dept", + session: "S", + location: "Contact Dept", startingTime: 16, - fstLocation: null, weekDay: 0, }, ], @@ -215,9 +213,9 @@ export default { timeData: [ { endingTime: 16, - secLocation: "MY 315", + session: "S", + location: "MY 315", startingTime: 13, - fstLocation: null, weekDay: 3, }, ], @@ -236,9 +234,9 @@ export default { timeData: [ { endingTime: 21, - secLocation: "MY 150", + session: "S", + location: "MY 150", startingTime: 18, - fstLocation: null, weekDay: 1, }, ], @@ -257,16 +255,16 @@ export default { timeData: [ { endingTime: 15, - secLocation: "MY 150", + session: "S", + location: "MY 150", startingTime: 13, - fstLocation: null, weekDay: 1, }, { endingTime: 14, - secLocation: "MY 150", + session: "S", + location: "MY 150", startingTime: 13, - fstLocation: null, weekDay: 4, }, ], @@ -285,9 +283,9 @@ export default { timeData: [ { endingTime: 21, - secLocation: "MY 150", + session: "S", + location: "MY 150", startingTime: 18, - fstLocation: null, weekDay: 1, }, ], @@ -306,9 +304,9 @@ export default { timeData: [ { endingTime: 17, - secLocation: "Contact Dept", + session: "S", + location: "Contact Dept", startingTime: 16, - fstLocation: null, weekDay: 4, }, ], @@ -327,9 +325,7 @@ export default { timeData: [ { endingTime: 25, - secLocation: null, startingTime: 25, - fstLocation: null, weekDay: 5, }, ], @@ -348,9 +344,9 @@ export default { timeData: [ { endingTime: 17, - secLocation: "Contact Dept", + session: "S", + location: "Contact Dept", startingTime: 16, - fstLocation: null, weekDay: 2, }, ], diff --git a/js/components/graph/__mocks__/ccc100-course-info.js b/js/components/graph/__mocks__/ccc100-course-info.js index 50e9142ef..9723f48eb 100644 --- a/js/components/graph/__mocks__/ccc100-course-info.js +++ b/js/components/graph/__mocks__/ccc100-course-info.js @@ -6,16 +6,16 @@ export default { timeData: [ { endingTime: 14, - secLocation: null, startingTime: 12, - fstLocation: "MY 150", + session: "F", + location: "MY 150", weekDay: 1, }, { endingTime: 14, - secLocation: null, startingTime: 13, - fstLocation: "MY 150", + session: "F", + location: "MY 150", weekDay: 3, }, ], @@ -34,16 +34,16 @@ export default { timeData: [ { endingTime: 15, - secLocation: null, startingTime: 13, - fstLocation: "BA 1160", + session: "F", + location: "BA 1160", weekDay: 2, }, { endingTime: 14, - secLocation: null, startingTime: 13, - fstLocation: "BA 1160", + session: "F", + location: "BA 1160", weekDay: 4, }, ], @@ -62,9 +62,9 @@ export default { timeData: [ { endingTime: 21, - secLocation: null, startingTime: 18, - fstLocation: "MY 150", + session: "F", + location: "MY 150", weekDay: 1, }, ], @@ -83,16 +83,16 @@ export default { timeData: [ { endingTime: 14, - secLocation: null, startingTime: 13, - fstLocation: "MY 150", + session: "F", + location: "MY 150", weekDay: 3, }, { endingTime: 14, - secLocation: null, startingTime: 12, - fstLocation: "MY 150", + session: "F", + location: "MY 150", weekDay: 1, }, ], @@ -111,9 +111,9 @@ export default { timeData: [ { endingTime: 21, - secLocation: null, startingTime: 18, - fstLocation: "MY 150", + session: "F", + location: "MY 150", weekDay: 1, }, ], @@ -132,9 +132,7 @@ export default { timeData: [ { endingTime: 25, - secLocation: null, startingTime: 25, - fstLocation: null, weekDay: 5, }, ], @@ -153,16 +151,16 @@ export default { timeData: [ { endingTime: 14, - secLocation: "MY 150", + session: "S", + location: "MY 150", startingTime: 13, - fstLocation: null, weekDay: 4, }, { endingTime: 15, - secLocation: "MY 150", + session: "S", + location: "MY 150", startingTime: 13, - fstLocation: null, weekDay: 1, }, ], @@ -194,9 +192,9 @@ export default { timeData: [ { endingTime: 17, - secLocation: "Contact Dept", + session: "S", + location: "Contact Dept", startingTime: 16, - fstLocation: null, weekDay: 0, }, ], @@ -215,9 +213,9 @@ export default { timeData: [ { endingTime: 16, - secLocation: "MY 315", + session: "S", + location: "MY 315", startingTime: 13, - fstLocation: null, weekDay: 3, }, ], @@ -236,9 +234,9 @@ export default { timeData: [ { endingTime: 21, - secLocation: "MY 150", + session: "S", + location: "MY 150", startingTime: 18, - fstLocation: null, weekDay: 1, }, ], @@ -257,16 +255,16 @@ export default { timeData: [ { endingTime: 15, - secLocation: "MY 150", + session: "S", + location: "MY 150", startingTime: 13, - fstLocation: null, weekDay: 1, }, { endingTime: 14, - secLocation: "MY 150", + session: "S", + location: "MY 150", startingTime: 13, - fstLocation: null, weekDay: 4, }, ], @@ -285,9 +283,9 @@ export default { timeData: [ { endingTime: 21, - secLocation: "MY 150", + session: "S", + location: "MY 150", startingTime: 18, - fstLocation: null, weekDay: 1, }, ], @@ -306,9 +304,9 @@ export default { timeData: [ { endingTime: 17, - secLocation: "Contact Dept", + session: "S", + location: "Contact Dept", startingTime: 16, - fstLocation: null, weekDay: 4, }, ], @@ -327,9 +325,7 @@ export default { timeData: [ { endingTime: 25, - secLocation: null, startingTime: 25, - fstLocation: null, weekDay: 5, }, ], @@ -348,9 +344,9 @@ export default { timeData: [ { endingTime: 17, - secLocation: "Contact Dept", + session: "S", + location: "Contact Dept", startingTime: 16, - fstLocation: null, weekDay: 2, }, ], diff --git a/js/components/grid/calendar.js.jsx b/js/components/grid/calendar.js.jsx index d89f8bbcc..a9af2c399 100644 --- a/js/components/grid/calendar.js.jsx +++ b/js/components/grid/calendar.js.jsx @@ -420,12 +420,12 @@ function createNewLectures(lectureSection, index, lectureSections) { return { courseCode: lectureSection.courseCode, session: lectureSection.session, + timeSession: time.session, day: time.weekDay, dayString: dayStrings[time.weekDay], startTime: time.startHour, endTime: time.endHour, - fstLocation: time.firstRoom, - secLocation: time.secondRoom, + location: time.location, inConflict: false, width: 1, dataSatisfied: lectureSection.dataSatisfied, From 97b1fa072e81ca5c369914a66621c4c9ccce3b4b Mon Sep 17 00:00:00 2001 From: Jason De Lanerolle Date: Tue, 9 Jun 2026 12:10:08 -0400 Subject: [PATCH 21/39] fix course controller tests --- .../Controllers/CourseControllerTests.hs | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/backend-test/Controllers/CourseControllerTests.hs b/backend-test/Controllers/CourseControllerTests.hs index 7237dad2b..02ae72c9e 100644 --- a/backend-test/Controllers/CourseControllerTests.hs +++ b/backend-test/Controllers/CourseControllerTests.hs @@ -58,18 +58,18 @@ retrieveCourseTestCases = } [ Time' { + session' = Just "F", weekDay' = 0.0, startHour' = 10.0, endHour' = 11.0, - firstLocation' = Just "MP", - secondLocation' = Nothing + location' = Just "MP" }, Time' { + session' = Just "F", weekDay' = 2.0, startHour' = 13.0, endHour' = 14.0, - firstLocation' = Just "SS", - secondLocation' = Nothing + location' = Just "SS" } ], MeetTime @@ -85,23 +85,23 @@ retrieveCourseTestCases = } [ Time' { + session' = Just "S", weekDay' = 1.0, startHour' = 10.0, endHour' = 11.0, - firstLocation' = Just "WW", - secondLocation' = Nothing + location' = Just "WW" }, Time' { + session' = Just "S", weekDay' = 4.0, startHour' = 13.0, endHour' = 14.0, - firstLocation' = Just "SS", - secondLocation' = Nothing + location' = Just "SS" } ] ], 200, - "{\"allMeetingTimes\":[{\"meetData\":{\"cap\":50,\"code\":\"STA238\",\"enrol\":15,\"extra\":0,\"instructor\":\"Instructor Name\",\"section\":\"LEC0101\",\"session\":\"F\",\"wait\":0},\"timeData\":[{\"endHour\":11,\"firstLocation\":{\"buildingAddress\":\"N/A\",\"buildingCode\":\"MP\",\"buildingLat\":1,\"buildingLng\":1,\"buildingName\":\"MP\",\"buildingPostalCode\":\"A1A 1A1\"},\"secondLocation\":null,\"startHour\":10,\"weekDay\":0},{\"endHour\":14,\"firstLocation\":{\"buildingAddress\":\"N/A\",\"buildingCode\":\"SS\",\"buildingLat\":1,\"buildingLng\":1,\"buildingName\":\"SS\",\"buildingPostalCode\":\"A1A 1A1\"},\"secondLocation\":null,\"startHour\":13,\"weekDay\":2}]}],\"breadth\":null,\"coreqs\":\"CSC108H1/ CSC110Y1/ CSC148H1 *Note: the corequisite may be completed either concurrently or in advance.\",\"description\":\"An introduction to statistical inference and practice. Statistical models and parameters, estimators of parameters and their statistical properties, methods of estimation, confidence intervals, hypothesis testing, likelihood function, the linear model. Use of statistical computation for data analysis and simulation.\",\"distribution\":null,\"exclusions\":\"ECO220Y1/ ECO227Y1/ GGR270H1/ PSY201H1/ SOC300H1/ SOC202H1/ SOC252H1/ STA220H1/ STA221H1/ STA255H1/ STA248H1/ STA261H1/ STA288H1/ EEB225H1/ STAB22H3/ STAB27H3/ STAB57H3/ STA220H5/ STA221H5/ STA258H5/ STA260H5/ ECO220Y5/ ECO227Y5\",\"name\":\"STA238H1\",\"prereqString\":\"STA237H1/ STA247H1/ STA257H1/ STAB52H3/ STA256H5\",\"title\":\"Probability, Statistics and Data Analysis II\",\"videoUrls\":[\"https://example.com/video1\",\"https://example.com/video2\"]}" + "{\"allMeetingTimes\":[{\"meetData\":{\"cap\":50,\"code\":\"STA238\",\"enrol\":15,\"extra\":0,\"instructor\":\"Instructor Name\",\"section\":\"LEC0101\",\"session\":\"F\",\"wait\":0},\"timeData\":[{\"endHour\":11,\"location\":{\"buildingAddress\":\"N/A\",\"buildingCode\":\"MP\",\"buildingLat\":1,\"buildingLng\":1,\"buildingName\":\"MP\",\"buildingPostalCode\":\"A1A 1A1\"},\"session\":\"F\",\"startHour\":10,\"weekDay\":0},{\"endHour\":14,\"location\":{\"buildingAddress\":\"N/A\",\"buildingCode\":\"SS\",\"buildingLat\":1,\"buildingLng\":1,\"buildingName\":\"SS\",\"buildingPostalCode\":\"A1A 1A1\"},\"session\":\"F\",\"startHour\":13,\"weekDay\":2}]}],\"breadth\":null,\"coreqs\":\"CSC108H1/ CSC110Y1/ CSC148H1 *Note: the corequisite may be completed either concurrently or in advance.\",\"description\":\"An introduction to statistical inference and practice. Statistical models and parameters, estimators of parameters and their statistical properties, methods of estimation, confidence intervals, hypothesis testing, likelihood function, the linear model. Use of statistical computation for data analysis and simulation.\",\"distribution\":null,\"exclusions\":\"ECO220Y1/ ECO227Y1/ GGR270H1/ PSY201H1/ SOC300H1/ SOC202H1/ SOC252H1/ STA220H1/ STA221H1/ STA255H1/ STA248H1/ STA261H1/ STA288H1/ EEB225H1/ STAB22H3/ STAB27H3/ STAB57H3/ STA220H5/ STA221H5/ STA258H5/ STA260H5/ ECO220Y5/ ECO227Y5\",\"name\":\"STA238H1\",\"prereqString\":\"STA237H1/ STA247H1/ STA257H1/ STAB52H3/ STA256H5\",\"title\":\"Probability, Statistics and Data Analysis II\",\"videoUrls\":[\"https://example.com/video1\",\"https://example.com/video2\"]}" ), ("Course exists with meeting times", @@ -132,23 +132,23 @@ retrieveCourseTestCases = } [ Time' { + session' = Just "F", weekDay' = 0.0, startHour' = 10.0, endHour' = 11.0, - firstLocation' = Just "MP", - secondLocation' = Nothing + location' = Just "MP" }, Time' { + session' = Just "F", weekDay' = 2.0, startHour' = 13.0, endHour' = 14.0, - firstLocation' = Just "SS", - secondLocation' = Nothing + location' = Just "SS" } ] ], 200, - "{\"allMeetingTimes\":[{\"meetData\":{\"cap\":50,\"code\":\"STA238\",\"enrol\":15,\"extra\":0,\"instructor\":\"Instructor Name\",\"section\":\"LEC0101\",\"session\":\"F\",\"wait\":0},\"timeData\":[{\"endHour\":11,\"firstLocation\":{\"buildingAddress\":\"N/A\",\"buildingCode\":\"MP\",\"buildingLat\":1,\"buildingLng\":1,\"buildingName\":\"MP\",\"buildingPostalCode\":\"A1A 1A1\"},\"secondLocation\":null,\"startHour\":10,\"weekDay\":0},{\"endHour\":14,\"firstLocation\":{\"buildingAddress\":\"N/A\",\"buildingCode\":\"SS\",\"buildingLat\":1,\"buildingLng\":1,\"buildingName\":\"SS\",\"buildingPostalCode\":\"A1A 1A1\"},\"secondLocation\":null,\"startHour\":13,\"weekDay\":2}]}],\"breadth\":null,\"coreqs\":\"CSC108H1/ CSC110Y1/ CSC148H1 *Note: the corequisite may be completed either concurrently or in advance.\",\"description\":\"An introduction to statistical inference and practice. Statistical models and parameters, estimators of parameters and their statistical properties, methods of estimation, confidence intervals, hypothesis testing, likelihood function, the linear model. Use of statistical computation for data analysis and simulation.\",\"distribution\":null,\"exclusions\":\"ECO220Y1/ ECO227Y1/ GGR270H1/ PSY201H1/ SOC300H1/ SOC202H1/ SOC252H1/ STA220H1/ STA221H1/ STA255H1/ STA248H1/ STA261H1/ STA288H1/ EEB225H1/ STAB22H3/ STAB27H3/ STAB57H3/ STA220H5/ STA221H5/ STA258H5/ STA260H5/ ECO220Y5/ ECO227Y5\",\"name\":\"STA238H1\",\"prereqString\":\"STA237H1/ STA247H1/ STA257H1/ STAB52H3/ STA256H5\",\"title\":\"Probability, Statistics and Data Analysis II\",\"videoUrls\":[\"https://example.com/video1\",\"https://example.com/video2\"]}" + "{\"allMeetingTimes\":[{\"meetData\":{\"cap\":50,\"code\":\"STA238\",\"enrol\":15,\"extra\":0,\"instructor\":\"Instructor Name\",\"section\":\"LEC0101\",\"session\":\"F\",\"wait\":0},\"timeData\":[{\"endHour\":11,\"location\":{\"buildingAddress\":\"N/A\",\"buildingCode\":\"MP\",\"buildingLat\":1,\"buildingLng\":1,\"buildingName\":\"MP\",\"buildingPostalCode\":\"A1A 1A1\"},\"session\":\"F\",\"startHour\":10,\"weekDay\":0},{\"endHour\":14,\"location\":{\"buildingAddress\":\"N/A\",\"buildingCode\":\"SS\",\"buildingLat\":1,\"buildingLng\":1,\"buildingName\":\"SS\",\"buildingPostalCode\":\"A1A 1A1\"},\"session\":\"F\",\"startHour\":13,\"weekDay\":2}]}],\"breadth\":null,\"coreqs\":\"CSC108H1/ CSC110Y1/ CSC148H1 *Note: the corequisite may be completed either concurrently or in advance.\",\"description\":\"An introduction to statistical inference and practice. Statistical models and parameters, estimators of parameters and their statistical properties, methods of estimation, confidence intervals, hypothesis testing, likelihood function, the linear model. Use of statistical computation for data analysis and simulation.\",\"distribution\":null,\"exclusions\":\"ECO220Y1/ ECO227Y1/ GGR270H1/ PSY201H1/ SOC300H1/ SOC202H1/ SOC252H1/ STA220H1/ STA221H1/ STA255H1/ STA248H1/ STA261H1/ STA288H1/ EEB225H1/ STAB22H3/ STAB27H3/ STAB57H3/ STA220H5/ STA221H5/ STA258H5/ STA260H5/ ECO220Y5/ ECO227Y5\",\"name\":\"STA238H1\",\"prereqString\":\"STA237H1/ STA247H1/ STA257H1/ STAB52H3/ STA256H5\",\"title\":\"Probability, Statistics and Data Analysis II\",\"videoUrls\":[\"https://example.com/video1\",\"https://example.com/video2\"]}" ), ("Course exists", @@ -253,11 +253,11 @@ insertBuildings = mapM_ insertBuilding where insertBuilding code = insert_ Building {buildingCode = code, buildingName = code, buildingAddress = "N/A", buildingPostalCode = "A1A 1A1", buildingLat = 1.0, buildingLng = 1.0} --- | Helper function to get a list of unique firstLocation' and secondLocation' values involved in a MeetTime +-- | Helper function to get a list of unique locations involved in a MeetTime getUniqueBuildings :: [MeetTime] -> [T.Text] -getUniqueBuildings = nub . concatMap getMeetBuildings +getUniqueBuildings = nub . concatMap getMeetBuilding where - getMeetBuildings (MeetTime _ times') = mapMaybe firstLocation' times' ++ mapMaybe secondLocation' times' + getMeetBuilding (MeetTime _ times') = mapMaybe location' times' -- | List of test cases as (label, input courses, expected output) indexTestCases :: [(String, [T.Text], String)] From ba03e3e8fe12e9231599cab0f01b9b2f7142517c Mon Sep 17 00:00:00 2001 From: Jason De Lanerolle Date: Tue, 9 Jun 2026 12:10:19 -0400 Subject: [PATCH 22/39] add mini changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f46458299..2d627fdb3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,7 +28,10 @@ - Removed `Location` datatype in favour of `Building` - Refactor tests to run directly on tuple input to prevent unnecessary unpacking and repacking - Renamed usages of the word "room" to "location" in the codebase to better reflect the data represented + +#### y-course-refactor mini changelog (to replace): - Refactor `Times` database schema to encompass only a single session of a course +- Change `Time` and `Time'` datatypes to match the database schema, and resolve resulting compilation and type errors ## [0.7.2] - 2025-12-10 From 3f3894e2e2ceffbb47523c344175f9cd5856fe41 Mon Sep 17 00:00:00 2001 From: David Liu Date: Tue, 9 Jun 2026 12:19:46 -0400 Subject: [PATCH 23/39] Release version 0.8.0 (#1730) --- CHANGELOG.md | 8 ++++++++ courseography.cabal | 2 +- package.json | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 613b6f1cd..bbc141545 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,14 @@ ### ✨ New features/enhancements +### 🐛 Bug fixes + +### 🔧 Internal changes + +## [0.8.0] - 2026-06-09 + +### ✨ New features/enhancements + - Added 404 status code return to `retrieveCourse` in `Controllers/Course` and added front-end tests for affected components - Updated Computer Science graph and configuration for 2026-27 - Added privacy-preserving analytics using GoatCounter and updated privacy policy diff --git a/courseography.cabal b/courseography.cabal index 3afe3530d..1995b7953 100644 --- a/courseography.cabal +++ b/courseography.cabal @@ -1,6 +1,6 @@ cabal-version: 3.0 name: courseography -version: 0.7.2.0 +version: 0.8.0.0 synopsis: Program and course planning app for the University of Toronto. description: A web application designed to aid students in planning their courses at the University of Toronto. diff --git a/package.json b/package.json index 52c76ebf8..29b381b11 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "courseography", - "version": "0.7.2", + "version": "0.8.0", "repository": "git@github.com:Courseography/courseography.git", "author": "David Liu ", "license": "GPL-3.0", From 5807048a8f16edef6939ea1f0123dffb4b1bd842 Mon Sep 17 00:00:00 2001 From: Jason De Lanerolle Date: Tue, 9 Jun 2026 12:25:16 -0400 Subject: [PATCH 24/39] fix shadowing in Models/Meeting --- app/Models/Meeting.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Models/Meeting.hs b/app/Models/Meeting.hs index 05678018b..ae158c2d0 100644 --- a/app/Models/Meeting.hs +++ b/app/Models/Meeting.hs @@ -27,10 +27,10 @@ buildMeetTimes meet = do -- | Queries the database for all information regarding a specific meeting for -- a @course@, returns a Meeting. returnMeeting :: T.Text -> T.Text -> T.Text -> SqlPersistM (Maybe (Entity Meeting)) -returnMeeting lowerStr sect session = do +returnMeeting lowerStr sect sess = do selectFirst [MeetingCode ==. T.toUpper lowerStr, MeetingSection ==. sect, - MeetingSession ==. session] + MeetingSession ==. sess] [] -- | Queries the database for all times regarding a specific meeting (lecture, tutorial or practial) for From 69b0aab1764e89178c24a55c418acd33fe16a226 Mon Sep 17 00:00:00 2001 From: Jason De Lanerolle Date: Tue, 9 Jun 2026 12:39:58 -0400 Subject: [PATCH 25/39] fix getimages shadowing --- app/Export/GetImages.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Export/GetImages.hs b/app/Export/GetImages.hs index 61afd80b0..578c81327 100644 --- a/app/Export/GetImages.hs +++ b/app/Export/GetImages.hs @@ -96,8 +96,8 @@ addCourseHelper (courseCode, courseSection, courseSession) currentSchedule (day, -- | Creates a timetable image based on schedule. generateTimetableImg :: [[[T.Text]]] -> T.Text -> FilePath -> IO FilePath generateTimetableImg schedule courseSession tempDir = do - let session = filter isAlphaNum (T.unpack courseSession) - sessionStem = if null session then "session" else session + let sess = filter isAlphaNum (T.unpack courseSession) + sessionStem = if null sess then "session" else sess pngPath = tempDir (sessionStem ++ ".png") svgText = renderTableHelper (zipWith (:) times schedule) courseSession withImageFile pngPath $ \hin -> From 56e925dd34277de4ad2eeb62bf12e2ef9d5c8f95 Mon Sep 17 00:00:00 2001 From: Jason De Lanerolle Date: Fri, 12 Jun 2026 20:53:41 -0400 Subject: [PATCH 26/39] skip test instead of commenting it out --- js/components/common/__tests__/GetTable.test.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/js/components/common/__tests__/GetTable.test.js b/js/components/common/__tests__/GetTable.test.js index 9808098af..8cd68784d 100644 --- a/js/components/common/__tests__/GetTable.test.js +++ b/js/components/common/__tests__/GetTable.test.js @@ -121,9 +121,6 @@ describe("getTable", () => { }) }) - /*** - * TODO: Re-implement this test once the logic for formatting Y courses is complete - describe("The occurence of the lecture has two locations ", () => { beforeEach(() => { meetingTime = [ @@ -164,7 +161,7 @@ describe("getTable", () => { }, ] }) - test("Both of the first and second location of the occurence are shown", () => { + test.skip("Both of the first and second location of the occurence are shown", () => { actual = wrapper.getTable(meetingTime, "F") expected = [ { @@ -180,7 +177,6 @@ describe("getTable", () => { }) }) - */ describe("The meeting time has two lectures each with one occurence", () => { beforeEach(() => { From 94819cd455ee5c6cb07920dfdc6de2d946bd2fde Mon Sep 17 00:00:00 2001 From: Jason De Lanerolle Date: Fri, 12 Jun 2026 20:58:34 -0400 Subject: [PATCH 27/39] rename fields --- app/Controllers/Timetable.hs | 30 ++-- app/Database/Tables.hs | 20 +-- app/Export/GetImages.hs | 4 +- app/Models/Meeting.hs | 4 +- .../Controllers/CourseControllerTests.hs | 28 ++-- .../graph/__mocks__/aaa100-course-info.js | 152 +++++++++--------- .../graph/__mocks__/bbb100-course-info.js | 152 +++++++++--------- .../graph/__mocks__/ccc100-course-info.js | 152 +++++++++--------- 8 files changed, 271 insertions(+), 271 deletions(-) diff --git a/app/Controllers/Timetable.hs b/app/Controllers/Timetable.hs index 6faa16021..9763698f4 100644 --- a/app/Controllers/Timetable.hs +++ b/app/Controllers/Timetable.hs @@ -45,11 +45,11 @@ gridResponse = -- | Returns an image of the timetable requested by the user. exportTimetableImageResponse :: ServerPart Response exportTimetableImageResponse = do - selectedSession <- lookText' "session" + session <- lookText' "session" selectedCourses <- lookText' "courses" liftIO $ withSystemTempDirectory "timetable-image" $ \tempDir -> do - pngPath <- getActiveTimetable selectedCourses selectedSession tempDir + pngPath <- getActiveTimetable selectedCourses session tempDir readImageData pngPath -- | Returns a PDF containing graph and timetable requested by the user. @@ -131,14 +131,14 @@ type Session = T.Text getCoursesInfo :: T.Text -> [(Code, Section, Session)] getCoursesInfo courses = map courseInfo allCourses where - courseInfo [code, sect, sess] = (code, sect, sess) + courseInfo [code, sect, session] = (code, sect, session) courseInfo _ = ("", "", "") allCourses = map (T.splitOn "-") (T.splitOn "_" courses) -- | Pulls either a Lecture, Tutorial or Pratical from the database. pullDatabase :: (Code, Section, Session) -> IO (Maybe MeetTime') -pullDatabase (code, sect, sess) = runDb $ do - meet <- returnMeeting code fullSection sess +pullDatabase (code, section, session) = runDb $ do + meet <- returnMeeting code fullSection session case meet of Nothing -> return Nothing Just x -> do @@ -147,11 +147,11 @@ pullDatabase (code, sect, sess) = runDb $ do return $ Just (MeetTime' (entityVal x) parsedTime) where fullSection - | T.isPrefixOf "L" sect = T.append "LEC" sectCode - | T.isPrefixOf "T" sect = T.append "TUT" sectCode - | T.isPrefixOf "P" sect = T.append "PRA" sectCode - | otherwise = sect - sectCode = T.tail sect + | T.isPrefixOf "L" section = T.append "LEC" sectCode + | T.isPrefixOf "T" section = T.append "TUT" sectCode + | T.isPrefixOf "P" section = T.append "PRA" sectCode + | otherwise = section + sectCode = T.tail section -- | The current date and time as obtained from the system. type SystemTime = String @@ -314,12 +314,12 @@ formatMinutes decimal = if minutes >= 10 then show minutes else '0' : show minut -- | Obtains all the dates for each course depending on its session. getDatesByCourse :: InfoTimeFieldsByDay -> Session -> IO DatesByDay -getDatesByCourse dataInOrder selectedSession - | selectedSession == "Y" = do +getDatesByCourse dataInOrder session + | session == "Y" = do fallDates <- mapM (getDatesByDay "F") dataInOrder winterDates <- mapM (getDatesByDay "S") dataInOrder return (fallDates ++ winterDates) - | otherwise = mapM (getDatesByDay selectedSession) dataInOrder + | otherwise = mapM (getDatesByDay session) dataInOrder -- | The string representation for a date in which an event -- occurs for the first time. @@ -333,8 +333,8 @@ type EndDate = String -- course takes place, depending on the course session. getDatesByDay :: Session -> [Time] -> IO (StartDate, EndDate) getDatesByDay _ [] = error "Failed to fetch dates" -getDatesByDay selectedSession (firstDate:_) - | selectedSession == "F" = do +getDatesByDay session (firstDate:_) + | session == "F" = do fallStart <- fallStartDate fallEnd <- fallEndDate formatDates $ getDates fallStart fallEnd dayOfWeek diff --git a/app/Database/Tables.hs b/app/Database/Tables.hs index f53896a33..98de06678 100644 --- a/app/Database/Tables.hs +++ b/app/Database/Tables.hs @@ -169,20 +169,20 @@ data SvgJSON = } deriving (Show, Generic) data Time' = - Time' { session' :: Maybe T.Text, + Time' { timeSession' :: Maybe T.Text, weekDay' :: Double, startHour' :: Double, endHour' :: Double, - location' :: Maybe T.Text + timeLocation' :: Maybe T.Text } deriving (Show, Generic) data Time = - Time { session :: Maybe T.Text, - weekDay :: Double, - startHour :: Double, - endHour :: Double, - location :: Maybe Building - } deriving (Show, Generic) + Time { timeSession :: Maybe T.Text, + weekDay :: Double, + startHour :: Double, + endHour :: Double, + timeLocation :: Maybe Building + } deriving (Show, Generic) -- | A Meeting with its associated Times. data MeetTime = MeetTime {meetInfo :: Meeting, timeInfo :: [Time'] } @@ -320,12 +320,12 @@ buildTime t = do buildTimes :: Key Meeting -> Time' -> Times buildTimes meetingKey t = - Times (session' t) + Times (timeSession' t) (weekDay' t) (startHour' t) (endHour' t) meetingKey - (location' t) + (timeLocation' t) -- | Given a building code, get the persistent Building associated with it getBuilding :: Maybe T.Text -> SqlPersistM (Maybe Building) diff --git a/app/Export/GetImages.hs b/app/Export/GetImages.hs index 578c81327..61afd80b0 100644 --- a/app/Export/GetImages.hs +++ b/app/Export/GetImages.hs @@ -96,8 +96,8 @@ addCourseHelper (courseCode, courseSection, courseSession) currentSchedule (day, -- | Creates a timetable image based on schedule. generateTimetableImg :: [[[T.Text]]] -> T.Text -> FilePath -> IO FilePath generateTimetableImg schedule courseSession tempDir = do - let sess = filter isAlphaNum (T.unpack courseSession) - sessionStem = if null sess then "session" else sess + let session = filter isAlphaNum (T.unpack courseSession) + sessionStem = if null session then "session" else session pngPath = tempDir (sessionStem ++ ".png") svgText = renderTableHelper (zipWith (:) times schedule) courseSession withImageFile pngPath $ \hin -> diff --git a/app/Models/Meeting.hs b/app/Models/Meeting.hs index ae158c2d0..05678018b 100644 --- a/app/Models/Meeting.hs +++ b/app/Models/Meeting.hs @@ -27,10 +27,10 @@ buildMeetTimes meet = do -- | Queries the database for all information regarding a specific meeting for -- a @course@, returns a Meeting. returnMeeting :: T.Text -> T.Text -> T.Text -> SqlPersistM (Maybe (Entity Meeting)) -returnMeeting lowerStr sect sess = do +returnMeeting lowerStr sect session = do selectFirst [MeetingCode ==. T.toUpper lowerStr, MeetingSection ==. sect, - MeetingSession ==. sess] + MeetingSession ==. session] [] -- | Queries the database for all times regarding a specific meeting (lecture, tutorial or practial) for diff --git a/backend-test/Controllers/CourseControllerTests.hs b/backend-test/Controllers/CourseControllerTests.hs index 02ae72c9e..311a52b2b 100644 --- a/backend-test/Controllers/CourseControllerTests.hs +++ b/backend-test/Controllers/CourseControllerTests.hs @@ -58,18 +58,18 @@ retrieveCourseTestCases = } [ Time' { - session' = Just "F", + timeSession' = Just "F", weekDay' = 0.0, startHour' = 10.0, endHour' = 11.0, - location' = Just "MP" + timeLocation' = Just "MP" }, Time' { - session' = Just "F", + timeSession' = Just "F", weekDay' = 2.0, startHour' = 13.0, endHour' = 14.0, - location' = Just "SS" + timeLocation' = Just "SS" } ], MeetTime @@ -85,18 +85,18 @@ retrieveCourseTestCases = } [ Time' { - session' = Just "S", + timeSession' = Just "S", weekDay' = 1.0, startHour' = 10.0, endHour' = 11.0, - location' = Just "WW" + timeLocation' = Just "WW" }, Time' { - session' = Just "S", + timeSession' = Just "S", weekDay' = 4.0, startHour' = 13.0, endHour' = 14.0, - location' = Just "SS" + timeLocation' = Just "SS" } ] ], @@ -132,18 +132,18 @@ retrieveCourseTestCases = } [ Time' { - session' = Just "F", + timeSession' = Just "F", weekDay' = 0.0, startHour' = 10.0, endHour' = 11.0, - location' = Just "MP" + timeLocation' = Just "MP" }, Time' { - session' = Just "F", + timeSession' = Just "F", weekDay' = 2.0, startHour' = 13.0, endHour' = 14.0, - location' = Just "SS" + timeLocation' = Just "SS" } ] ], @@ -255,9 +255,9 @@ insertBuildings = mapM_ insertBuilding -- | Helper function to get a list of unique locations involved in a MeetTime getUniqueBuildings :: [MeetTime] -> [T.Text] -getUniqueBuildings = nub . concatMap getMeetBuilding +getUniqueBuildings = nub . concatMap getMeetBuildings where - getMeetBuilding (MeetTime _ times') = mapMaybe location' times' + getMeetBuildings (MeetTime _ times') = mapMaybe timeLocation' times' -- | List of test cases as (label, input courses, expected output) indexTestCases :: [(String, [T.Text], String)] diff --git a/js/components/graph/__mocks__/aaa100-course-info.js b/js/components/graph/__mocks__/aaa100-course-info.js index 706d6c337..bffc22fa9 100644 --- a/js/components/graph/__mocks__/aaa100-course-info.js +++ b/js/components/graph/__mocks__/aaa100-course-info.js @@ -5,17 +5,17 @@ export default { { timeData: [ { - endingTime: 14, - startingTime: 12, - session: "F", - location: "MY 150", + endHour: 14, + startHour: 12, + timeSession: "F", + timeLocation: "MY 150", weekDay: 1, }, { - endingTime: 14, - startingTime: 13, - session: "F", - location: "MY 150", + endHour: 14, + startHour: 13, + timeSession: "F", + timeLocation: "MY 150", weekDay: 3, }, ], @@ -33,17 +33,17 @@ export default { { timeData: [ { - endingTime: 15, - startingTime: 13, - session: "F", - location: "BA 1160", + endHour: 15, + startHour: 13, + timeSession: "F", + timeLocation: "BA 1160", weekDay: 2, }, { - endingTime: 14, - startingTime: 13, - session: "F", - location: "BA 1160", + endHour: 14, + startHour: 13, + timeSession: "F", + timeLocation: "BA 1160", weekDay: 4, }, ], @@ -61,10 +61,10 @@ export default { { timeData: [ { - endingTime: 21, - startingTime: 18, - session: "F", - location: "MY 150", + endHour: 21, + startHour: 18, + timeSession: "F", + timeLocation: "MY 150", weekDay: 1, }, ], @@ -82,17 +82,17 @@ export default { { timeData: [ { - endingTime: 14, - startingTime: 13, - session: "F", - location: "MY 150", + endHour: 14, + startHour: 13, + timeSession: "F", + timeLocation: "MY 150", weekDay: 3, }, { - endingTime: 14, - startingTime: 12, - session: "F", - location: "MY 150", + endHour: 14, + startHour: 12, + timeSession: "F", + timeLocation: "MY 150", weekDay: 1, }, ], @@ -110,10 +110,10 @@ export default { { timeData: [ { - endingTime: 21, - startingTime: 18, - session: "F", - location: "MY 150", + endHour: 21, + startHour: 18, + timeSession: "F", + timeLocation: "MY 150", weekDay: 1, }, ], @@ -131,8 +131,8 @@ export default { { timeData: [ { - endingTime: 25, - startingTime: 25, + endHour: 25, + startHour: 25, weekDay: 5, }, ], @@ -150,17 +150,17 @@ export default { { timeData: [ { - endingTime: 14, - session: "S", - location: "MY 150", - startingTime: 13, + endHour: 14, + timeSession: "S", + timeLocation: "MY 150", + startHour: 13, weekDay: 4, }, { - endingTime: 15, - session: "S", - location: "MY 150", - startingTime: 13, + endHour: 15, + timeSession: "S", + timeLocation: "MY 150", + startHour: 13, weekDay: 1, }, ], @@ -191,10 +191,10 @@ export default { { timeData: [ { - endingTime: 17, - session: "S", - location: "Contact Dept", - startingTime: 16, + endHour: 17, + timeSession: "S", + timeLocation: "Contact Dept", + startHour: 16, weekDay: 0, }, ], @@ -212,10 +212,10 @@ export default { { timeData: [ { - endingTime: 16, - session: "S", - location: "MY 315", - startingTime: 13, + endHour: 16, + timeSession: "S", + timeLocation: "MY 315", + startHour: 13, weekDay: 3, }, ], @@ -233,10 +233,10 @@ export default { { timeData: [ { - endingTime: 21, - session: "S", - location: "MY 150", - startingTime: 18, + endHour: 21, + timeSession: "S", + timeLocation: "MY 150", + startHour: 18, weekDay: 1, }, ], @@ -254,17 +254,17 @@ export default { { timeData: [ { - endingTime: 15, - session: "S", - location: "MY 150", - startingTime: 13, + endHour: 15, + timeSession: "S", + timeLocation: "MY 150", + startHour: 13, weekDay: 1, }, { - endingTime: 14, - session: "S", - location: "MY 150", - startingTime: 13, + endHour: 14, + timeSession: "S", + timeLocation: "MY 150", + startHour: 13, weekDay: 4, }, ], @@ -282,10 +282,10 @@ export default { { timeData: [ { - endingTime: 21, - session: "S", - location: "MY 150", - startingTime: 18, + endHour: 21, + timeSession: "S", + timeLocation: "MY 150", + startHour: 18, weekDay: 1, }, ], @@ -303,10 +303,10 @@ export default { { timeData: [ { - endingTime: 17, - session: "S", - location: "Contact Dept", - startingTime: 16, + endHour: 17, + timeSession: "S", + timeLocation: "Contact Dept", + startHour: 16, weekDay: 4, }, ], @@ -324,8 +324,8 @@ export default { { timeData: [ { - endingTime: 25, - startingTime: 25, + endHour: 25, + startHour: 25, weekDay: 5, }, ], @@ -343,10 +343,10 @@ export default { { timeData: [ { - endingTime: 17, - session: "S", - location: "Contact Dept", - startingTime: 16, + endHour: 17, + timeSession: "S", + timeLocation: "Contact Dept", + startHour: 16, weekDay: 2, }, ], diff --git a/js/components/graph/__mocks__/bbb100-course-info.js b/js/components/graph/__mocks__/bbb100-course-info.js index e85c8a23d..5457bd1c7 100644 --- a/js/components/graph/__mocks__/bbb100-course-info.js +++ b/js/components/graph/__mocks__/bbb100-course-info.js @@ -5,17 +5,17 @@ export default { { timeData: [ { - endingTime: 14, - startingTime: 12, - session: "F", - location: "MY 150", + endHour: 14, + startHour: 12, + timeSession: "F", + timeLocation: "MY 150", weekDay: 1, }, { - endingTime: 14, - startingTime: 13, - session: "F", - location: "MY 150", + endHour: 14, + startHour: 13, + timeSession: "F", + timeLocation: "MY 150", weekDay: 3, }, ], @@ -33,17 +33,17 @@ export default { { timeData: [ { - endingTime: 15, - startingTime: 13, - session: "F", - location: "BA 1160", + endHour: 15, + startHour: 13, + timeSession: "F", + timeLocation: "BA 1160", weekDay: 2, }, { - endingTime: 14, - startingTime: 13, - session: "F", - location: "BA 1160", + endHour: 14, + startHour: 13, + timeSession: "F", + timeLocation: "BA 1160", weekDay: 4, }, ], @@ -61,10 +61,10 @@ export default { { timeData: [ { - endingTime: 21, - startingTime: 18, - session: "F", - location: "MY 150", + endHour: 21, + startHour: 18, + timeSession: "F", + timeLocation: "MY 150", weekDay: 1, }, ], @@ -82,17 +82,17 @@ export default { { timeData: [ { - endingTime: 14, - startingTime: 13, - session: "F", - location: "MY 150", + endHour: 14, + startHour: 13, + timeSession: "F", + timeLocation: "MY 150", weekDay: 3, }, { - endingTime: 14, - startingTime: 12, - session: "F", - location: "MY 150", + endHour: 14, + startHour: 12, + timeSession: "F", + timeLocation: "MY 150", weekDay: 1, }, ], @@ -110,10 +110,10 @@ export default { { timeData: [ { - endingTime: 21, - startingTime: 18, - session: "F", - location: "MY 150", + endHour: 21, + startHour: 18, + timeSession: "F", + timeLocation: "MY 150", weekDay: 1, }, ], @@ -131,8 +131,8 @@ export default { { timeData: [ { - endingTime: 25, - startingTime: 25, + endHour: 25, + startHour: 25, weekDay: 5, }, ], @@ -150,17 +150,17 @@ export default { { timeData: [ { - endingTime: 14, - session: "S", - location: "MY 150", - startingTime: 13, + endHour: 14, + timeSession: "S", + timeLocation: "MY 150", + startHour: 13, weekDay: 4, }, { - endingTime: 15, - session: "S", - location: "MY 150", - startingTime: 13, + endHour: 15, + timeSession: "S", + timeLocation: "MY 150", + startHour: 13, weekDay: 1, }, ], @@ -191,10 +191,10 @@ export default { { timeData: [ { - endingTime: 17, - session: "S", - location: "Contact Dept", - startingTime: 16, + endHour: 17, + timeSession: "S", + timeLocation: "Contact Dept", + startHour: 16, weekDay: 0, }, ], @@ -212,10 +212,10 @@ export default { { timeData: [ { - endingTime: 16, - session: "S", - location: "MY 315", - startingTime: 13, + endHour: 16, + timeSession: "S", + timeLocation: "MY 315", + startHour: 13, weekDay: 3, }, ], @@ -233,10 +233,10 @@ export default { { timeData: [ { - endingTime: 21, - session: "S", - location: "MY 150", - startingTime: 18, + endHour: 21, + timeSession: "S", + timeLocation: "MY 150", + startHour: 18, weekDay: 1, }, ], @@ -254,17 +254,17 @@ export default { { timeData: [ { - endingTime: 15, - session: "S", - location: "MY 150", - startingTime: 13, + endHour: 15, + timeSession: "S", + timeLocation: "MY 150", + startHour: 13, weekDay: 1, }, { - endingTime: 14, - session: "S", - location: "MY 150", - startingTime: 13, + endHour: 14, + timeSession: "S", + timeLocation: "MY 150", + startHour: 13, weekDay: 4, }, ], @@ -282,10 +282,10 @@ export default { { timeData: [ { - endingTime: 21, - session: "S", - location: "MY 150", - startingTime: 18, + endHour: 21, + timeSession: "S", + timeLocation: "MY 150", + startHour: 18, weekDay: 1, }, ], @@ -303,10 +303,10 @@ export default { { timeData: [ { - endingTime: 17, - session: "S", - location: "Contact Dept", - startingTime: 16, + endHour: 17, + timeSession: "S", + timeLocation: "Contact Dept", + startHour: 16, weekDay: 4, }, ], @@ -324,8 +324,8 @@ export default { { timeData: [ { - endingTime: 25, - startingTime: 25, + endHour: 25, + startHour: 25, weekDay: 5, }, ], @@ -343,10 +343,10 @@ export default { { timeData: [ { - endingTime: 17, - session: "S", - location: "Contact Dept", - startingTime: 16, + endHour: 17, + timeSession: "S", + timeLocation: "Contact Dept", + startHour: 16, weekDay: 2, }, ], diff --git a/js/components/graph/__mocks__/ccc100-course-info.js b/js/components/graph/__mocks__/ccc100-course-info.js index 9723f48eb..52dc91bcd 100644 --- a/js/components/graph/__mocks__/ccc100-course-info.js +++ b/js/components/graph/__mocks__/ccc100-course-info.js @@ -5,17 +5,17 @@ export default { { timeData: [ { - endingTime: 14, - startingTime: 12, - session: "F", - location: "MY 150", + endHour: 14, + startHour: 12, + timeSession: "F", + timeLocation: "MY 150", weekDay: 1, }, { - endingTime: 14, - startingTime: 13, - session: "F", - location: "MY 150", + endHour: 14, + startHour: 13, + timeSession: "F", + timeLocation: "MY 150", weekDay: 3, }, ], @@ -33,17 +33,17 @@ export default { { timeData: [ { - endingTime: 15, - startingTime: 13, - session: "F", - location: "BA 1160", + endHour: 15, + startHour: 13, + timeSession: "F", + timeLocation: "BA 1160", weekDay: 2, }, { - endingTime: 14, - startingTime: 13, - session: "F", - location: "BA 1160", + endHour: 14, + startHour: 13, + timeSession: "F", + timeLocation: "BA 1160", weekDay: 4, }, ], @@ -61,10 +61,10 @@ export default { { timeData: [ { - endingTime: 21, - startingTime: 18, - session: "F", - location: "MY 150", + endHour: 21, + startHour: 18, + timeSession: "F", + timeLocation: "MY 150", weekDay: 1, }, ], @@ -82,17 +82,17 @@ export default { { timeData: [ { - endingTime: 14, - startingTime: 13, - session: "F", - location: "MY 150", + endHour: 14, + startHour: 13, + timeSession: "F", + timeLocation: "MY 150", weekDay: 3, }, { - endingTime: 14, - startingTime: 12, - session: "F", - location: "MY 150", + endHour: 14, + startHour: 12, + timeSession: "F", + timeLocation: "MY 150", weekDay: 1, }, ], @@ -110,10 +110,10 @@ export default { { timeData: [ { - endingTime: 21, - startingTime: 18, - session: "F", - location: "MY 150", + endHour: 21, + startHour: 18, + timeSession: "F", + timeLocation: "MY 150", weekDay: 1, }, ], @@ -131,8 +131,8 @@ export default { { timeData: [ { - endingTime: 25, - startingTime: 25, + endHour: 25, + startHour: 25, weekDay: 5, }, ], @@ -150,17 +150,17 @@ export default { { timeData: [ { - endingTime: 14, - session: "S", - location: "MY 150", - startingTime: 13, + endHour: 14, + timeSession: "S", + timeLocation: "MY 150", + startHour: 13, weekDay: 4, }, { - endingTime: 15, - session: "S", - location: "MY 150", - startingTime: 13, + endHour: 15, + timeSession: "S", + timeLocation: "MY 150", + startHour: 13, weekDay: 1, }, ], @@ -191,10 +191,10 @@ export default { { timeData: [ { - endingTime: 17, - session: "S", - location: "Contact Dept", - startingTime: 16, + endHour: 17, + timeSession: "S", + timeLocation: "Contact Dept", + startHour: 16, weekDay: 0, }, ], @@ -212,10 +212,10 @@ export default { { timeData: [ { - endingTime: 16, - session: "S", - location: "MY 315", - startingTime: 13, + endHour: 16, + timeSession: "S", + timeLocation: "MY 315", + startHour: 13, weekDay: 3, }, ], @@ -233,10 +233,10 @@ export default { { timeData: [ { - endingTime: 21, - session: "S", - location: "MY 150", - startingTime: 18, + endHour: 21, + timeSession: "S", + timeLocation: "MY 150", + startHour: 18, weekDay: 1, }, ], @@ -254,17 +254,17 @@ export default { { timeData: [ { - endingTime: 15, - session: "S", - location: "MY 150", - startingTime: 13, + endHour: 15, + timeSession: "S", + timeLocation: "MY 150", + startHour: 13, weekDay: 1, }, { - endingTime: 14, - session: "S", - location: "MY 150", - startingTime: 13, + endHour: 14, + timeSession: "S", + timeLocation: "MY 150", + startHour: 13, weekDay: 4, }, ], @@ -282,10 +282,10 @@ export default { { timeData: [ { - endingTime: 21, - session: "S", - location: "MY 150", - startingTime: 18, + endHour: 21, + timeSession: "S", + timeLocation: "MY 150", + startHour: 18, weekDay: 1, }, ], @@ -303,10 +303,10 @@ export default { { timeData: [ { - endingTime: 17, - session: "S", - location: "Contact Dept", - startingTime: 16, + endHour: 17, + timeSession: "S", + timeLocation: "Contact Dept", + startHour: 16, weekDay: 4, }, ], @@ -324,8 +324,8 @@ export default { { timeData: [ { - endingTime: 25, - startingTime: 25, + endHour: 25, + startHour: 25, weekDay: 5, }, ], @@ -343,10 +343,10 @@ export default { { timeData: [ { - endingTime: 17, - session: "S", - location: "Contact Dept", - startingTime: 16, + endHour: 17, + timeSession: "S", + timeLocation: "Contact Dept", + startHour: 16, weekDay: 2, }, ], From c44589731a0019c1a8c83a8b0375381f3654ed63 Mon Sep 17 00:00:00 2001 From: Jason De Lanerolle Date: Fri, 12 Jun 2026 21:06:54 -0400 Subject: [PATCH 28/39] fix tests 2 --- backend-test/Controllers/CourseControllerTests.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend-test/Controllers/CourseControllerTests.hs b/backend-test/Controllers/CourseControllerTests.hs index 311a52b2b..674379538 100644 --- a/backend-test/Controllers/CourseControllerTests.hs +++ b/backend-test/Controllers/CourseControllerTests.hs @@ -101,7 +101,7 @@ retrieveCourseTestCases = ] ], 200, - "{\"allMeetingTimes\":[{\"meetData\":{\"cap\":50,\"code\":\"STA238\",\"enrol\":15,\"extra\":0,\"instructor\":\"Instructor Name\",\"section\":\"LEC0101\",\"session\":\"F\",\"wait\":0},\"timeData\":[{\"endHour\":11,\"location\":{\"buildingAddress\":\"N/A\",\"buildingCode\":\"MP\",\"buildingLat\":1,\"buildingLng\":1,\"buildingName\":\"MP\",\"buildingPostalCode\":\"A1A 1A1\"},\"session\":\"F\",\"startHour\":10,\"weekDay\":0},{\"endHour\":14,\"location\":{\"buildingAddress\":\"N/A\",\"buildingCode\":\"SS\",\"buildingLat\":1,\"buildingLng\":1,\"buildingName\":\"SS\",\"buildingPostalCode\":\"A1A 1A1\"},\"session\":\"F\",\"startHour\":13,\"weekDay\":2}]}],\"breadth\":null,\"coreqs\":\"CSC108H1/ CSC110Y1/ CSC148H1 *Note: the corequisite may be completed either concurrently or in advance.\",\"description\":\"An introduction to statistical inference and practice. Statistical models and parameters, estimators of parameters and their statistical properties, methods of estimation, confidence intervals, hypothesis testing, likelihood function, the linear model. Use of statistical computation for data analysis and simulation.\",\"distribution\":null,\"exclusions\":\"ECO220Y1/ ECO227Y1/ GGR270H1/ PSY201H1/ SOC300H1/ SOC202H1/ SOC252H1/ STA220H1/ STA221H1/ STA255H1/ STA248H1/ STA261H1/ STA288H1/ EEB225H1/ STAB22H3/ STAB27H3/ STAB57H3/ STA220H5/ STA221H5/ STA258H5/ STA260H5/ ECO220Y5/ ECO227Y5\",\"name\":\"STA238H1\",\"prereqString\":\"STA237H1/ STA247H1/ STA257H1/ STAB52H3/ STA256H5\",\"title\":\"Probability, Statistics and Data Analysis II\",\"videoUrls\":[\"https://example.com/video1\",\"https://example.com/video2\"]}" + "{\"allMeetingTimes\":[{\"meetData\":{\"cap\":50,\"code\":\"STA238\",\"enrol\":15,\"extra\":0,\"instructor\":\"Instructor Name\",\"section\":\"LEC0101\",\"session\":\"F\",\"wait\":0},\"timeData\":[{\"endHour\":11,\"startHour\":10,\"timeLocation\":{\"buildingAddress\":\"N/A\",\"buildingCode\":\"MP\",\"buildingLat\":1,\"buildingLng\":1,\"buildingName\":\"MP\",\"buildingPostalCode\":\"A1A 1A1\"},\"timeSession\":\"F\",\"weekDay\":0},{\"endHour\":14,\"startHour\":13,\"timeLocation\":{\"buildingAddress\":\"N/A\",\"buildingCode\":\"SS\",\"buildingLat\":1,\"buildingLng\":1,\"buildingName\":\"SS\",\"buildingPostalCode\":\"A1A 1A1\"},\"timeSession\":\"F\",\"weekDay\":2}]}],\"breadth\":null,\"coreqs\":\"CSC108H1/ CSC110Y1/ CSC148H1 *Note: the corequisite may be completed either concurrently or in advance.\",\"description\":\"An introduction to statistical inference and practice. Statistical models and parameters, estimators of parameters and their statistical properties, methods of estimation, confidence intervals, hypothesis testing, likelihood function, the linear model. Use of statistical computation for data analysis and simulation.\",\"distribution\":null,\"exclusions\":\"ECO220Y1/ ECO227Y1/ GGR270H1/ PSY201H1/ SOC300H1/ SOC202H1/ SOC252H1/ STA220H1/ STA221H1/ STA255H1/ STA248H1/ STA261H1/ STA288H1/ EEB225H1/ STAB22H3/ STAB27H3/ STAB57H3/ STA220H5/ STA221H5/ STA258H5/ STA260H5/ ECO220Y5/ ECO227Y5\",\"name\":\"STA238H1\",\"prereqString\":\"STA237H1/ STA247H1/ STA257H1/ STAB52H3/ STA256H5\",\"title\":\"Probability, Statistics and Data Analysis II\",\"videoUrls\":[\"https://example.com/video1\",\"https://example.com/video2\"]}" ), ("Course exists with meeting times", @@ -148,7 +148,7 @@ retrieveCourseTestCases = ] ], 200, - "{\"allMeetingTimes\":[{\"meetData\":{\"cap\":50,\"code\":\"STA238\",\"enrol\":15,\"extra\":0,\"instructor\":\"Instructor Name\",\"section\":\"LEC0101\",\"session\":\"F\",\"wait\":0},\"timeData\":[{\"endHour\":11,\"location\":{\"buildingAddress\":\"N/A\",\"buildingCode\":\"MP\",\"buildingLat\":1,\"buildingLng\":1,\"buildingName\":\"MP\",\"buildingPostalCode\":\"A1A 1A1\"},\"session\":\"F\",\"startHour\":10,\"weekDay\":0},{\"endHour\":14,\"location\":{\"buildingAddress\":\"N/A\",\"buildingCode\":\"SS\",\"buildingLat\":1,\"buildingLng\":1,\"buildingName\":\"SS\",\"buildingPostalCode\":\"A1A 1A1\"},\"session\":\"F\",\"startHour\":13,\"weekDay\":2}]}],\"breadth\":null,\"coreqs\":\"CSC108H1/ CSC110Y1/ CSC148H1 *Note: the corequisite may be completed either concurrently or in advance.\",\"description\":\"An introduction to statistical inference and practice. Statistical models and parameters, estimators of parameters and their statistical properties, methods of estimation, confidence intervals, hypothesis testing, likelihood function, the linear model. Use of statistical computation for data analysis and simulation.\",\"distribution\":null,\"exclusions\":\"ECO220Y1/ ECO227Y1/ GGR270H1/ PSY201H1/ SOC300H1/ SOC202H1/ SOC252H1/ STA220H1/ STA221H1/ STA255H1/ STA248H1/ STA261H1/ STA288H1/ EEB225H1/ STAB22H3/ STAB27H3/ STAB57H3/ STA220H5/ STA221H5/ STA258H5/ STA260H5/ ECO220Y5/ ECO227Y5\",\"name\":\"STA238H1\",\"prereqString\":\"STA237H1/ STA247H1/ STA257H1/ STAB52H3/ STA256H5\",\"title\":\"Probability, Statistics and Data Analysis II\",\"videoUrls\":[\"https://example.com/video1\",\"https://example.com/video2\"]}" + "{\"allMeetingTimes\":[{\"meetData\":{\"cap\":50,\"code\":\"STA238\",\"enrol\":15,\"extra\":0,\"instructor\":\"Instructor Name\",\"section\":\"LEC0101\",\"session\":\"F\",\"wait\":0},\"timeData\":[{\"endHour\":11,\"startHour\":10,\"timeLocation\":{\"buildingAddress\":\"N/A\",\"buildingCode\":\"MP\",\"buildingLat\":1,\"buildingLng\":1,\"buildingName\":\"MP\",\"buildingPostalCode\":\"A1A 1A1\"},\"timeSession\":\"F\",\"weekDay\":0},{\"endHour\":14,\"startHour\":13,\"timeLocation\":{\"buildingAddress\":\"N/A\",\"buildingCode\":\"SS\",\"buildingLat\":1,\"buildingLng\":1,\"buildingName\":\"SS\",\"buildingPostalCode\":\"A1A 1A1\"},\"timeSession\":\"F\",\"weekDay\":2}]}],\"breadth\":null,\"coreqs\":\"CSC108H1/ CSC110Y1/ CSC148H1 *Note: the corequisite may be completed either concurrently or in advance.\",\"description\":\"An introduction to statistical inference and practice. Statistical models and parameters, estimators of parameters and their statistical properties, methods of estimation, confidence intervals, hypothesis testing, likelihood function, the linear model. Use of statistical computation for data analysis and simulation.\",\"distribution\":null,\"exclusions\":\"ECO220Y1/ ECO227Y1/ GGR270H1/ PSY201H1/ SOC300H1/ SOC202H1/ SOC252H1/ STA220H1/ STA221H1/ STA255H1/ STA248H1/ STA261H1/ STA288H1/ EEB225H1/ STAB22H3/ STAB27H3/ STAB57H3/ STA220H5/ STA221H5/ STA258H5/ STA260H5/ ECO220Y5/ ECO227Y5\",\"name\":\"STA238H1\",\"prereqString\":\"STA237H1/ STA247H1/ STA257H1/ STAB52H3/ STA256H5\",\"title\":\"Probability, Statistics and Data Analysis II\",\"videoUrls\":[\"https://example.com/video1\",\"https://example.com/video2\"]}" ), ("Course exists", From ded4583177a6f6566ca27fbbd59da7398a983212 Mon Sep 17 00:00:00 2001 From: Jason De Lanerolle Date: Fri, 12 Jun 2026 21:23:29 -0400 Subject: [PATCH 29/39] rename in frontend --- .../common/__tests__/GetTable.test.js | 28 +++++++++---------- js/components/common/react_modal.js.jsx | 4 +-- js/components/grid/calendar.js.jsx | 4 +-- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/js/components/common/__tests__/GetTable.test.js b/js/components/common/__tests__/GetTable.test.js index 8cd68784d..25641cda0 100644 --- a/js/components/common/__tests__/GetTable.test.js +++ b/js/components/common/__tests__/GetTable.test.js @@ -25,7 +25,7 @@ describe("getTable", () => { timeData: [ { endHour: 17, - location: { + timeLocation: { buildingAddress: "80 St. George Street", buildingCode: "LM", buildingName: "Lash Miller Chemical Laboratories", @@ -33,7 +33,7 @@ describe("getTable", () => { buildingLng: -79.39841172598216, buildingPostalCode: "M5S 3H6", }, - session: "F", + timeSession: "F", startHour: 15, weekDay: 1, }, @@ -74,7 +74,7 @@ describe("getTable", () => { timeData: [ { endHour: 17, - location: { + timeLocation: { buildingAddress: "15 King's College Circle", buildingCode: "UC", buildingName: "University College", @@ -82,13 +82,13 @@ describe("getTable", () => { buildingLng: -79.395181775127, buildingPostalCode: "M5S 3H7", }, - session: "F", + timeSession: "F", startHour: 16, weekDay: 3, }, { endHour: 17, - location: { + timeLocation: { buildingAddress: "80 St. George Street", buildingCode: "LM", buildingName: "Lash Miller Chemical Laboratories", @@ -96,7 +96,7 @@ describe("getTable", () => { buildingLng: -79.39841172598216, buildingPostalCode: "M5S 3H6", }, - session: "F", + timeSession: "F", startHour: 15, weekDay: 1, }, @@ -195,7 +195,7 @@ describe("getTable", () => { timeData: [ { endHour: 17, - location: { + timeLocation: { buildingAddress: "80 St. George Street", buildingCode: "LM", buildingName: "Lash Miller Chemical Laboratories", @@ -203,7 +203,7 @@ describe("getTable", () => { buildingLng: -79.39841172598216, buildingPostalCode: "M5S 3H6", }, - session: "F", + timeSession: "F", startHour: 15, weekDay: 1, }, @@ -223,7 +223,7 @@ describe("getTable", () => { timeData: [ { endHour: 17, - location: { + timeLocation: { buildingAddress: "80 St. George Street", buildingCode: "LM", buildingName: "Lash Miller Chemical Laboratories", @@ -231,7 +231,7 @@ describe("getTable", () => { buildingLng: -79.39841172598216, buildingPostalCode: "M5S 3H6", }, - session: "F", + timeSession: "F", startHour: 15, weekDay: 1, }, @@ -280,8 +280,8 @@ describe("getTable", () => { timeData: [ { endHour: 16, - location: null, - session: "F", + timeLocation: null, + timeSession: "F", startHour: 14, weekDay: 0, }, @@ -301,7 +301,7 @@ describe("getTable", () => { timeData: [ { endHour: 17, - location: { + timeLocation: { buildingAddress: "80 St. George Street", buildingCode: "LM", buildingName: "Lash Miller Chemical Laboratories", @@ -309,7 +309,7 @@ describe("getTable", () => { buildingLng: -79.39841172598216, buildingPostalCode: "M5S 3H6", }, - session: "F", + timeSession: "F", startHour: 15, weekDay: 1, }, diff --git a/js/components/common/react_modal.js.jsx b/js/components/common/react_modal.js.jsx index e857258d2..996e7fac8 100644 --- a/js/components/common/react_modal.js.jsx +++ b/js/components/common/react_modal.js.jsx @@ -149,8 +149,8 @@ class CourseModal extends React.Component { ) sortedTimeData.map(occurrence => { let location = " " - if (occurrence.location !== null && occurrence.location !== undefined) { - location = occurrence.location.buildingCode + if (occurrence.timeLocation !== null && occurrence.timeLocation !== undefined) { + location = occurrence.timeLocation.buildingCode } occurrences.locations.push(location) occurrences.times.push( diff --git a/js/components/grid/calendar.js.jsx b/js/components/grid/calendar.js.jsx index a9af2c399..5f3ca1e04 100644 --- a/js/components/grid/calendar.js.jsx +++ b/js/components/grid/calendar.js.jsx @@ -420,12 +420,12 @@ function createNewLectures(lectureSection, index, lectureSections) { return { courseCode: lectureSection.courseCode, session: lectureSection.session, - timeSession: time.session, + timeSession: time.timeSession, day: time.weekDay, dayString: dayStrings[time.weekDay], startTime: time.startHour, endTime: time.endHour, - location: time.location, + location: time.timeLocation, inConflict: false, width: 1, dataSatisfied: lectureSection.dataSatisfied, From 31a48aee9e04fa915137d1e0c55e6928e4d2a490 Mon Sep 17 00:00:00 2001 From: Angelina Jiang <43974738+AngelsandDevsLOL@users.noreply.github.com> Date: Wed, 17 Jun 2026 10:29:03 -0400 Subject: [PATCH 30/39] Renamed Courses datatype and table to Course (#1732) --- CHANGELOG.md | 2 + app/Controllers/Course.hs | 6 +- app/Database/CourseVideoSeed.hs | 2 +- app/Database/Migrations.hs | 9 +- app/Database/Tables.hs | 6 +- app/Export/GetImages.hs | 2 +- app/Models/Course.hs | 58 +++++------ app/WebParsing/ArtSciParser.hs | 28 +++--- .../Controllers/CourseControllerTests.hs | 96 +++++++++---------- .../Controllers/GenerateControllerTests.hs | 4 +- backend-test/TestHelpers.hs | 2 +- 11 files changed, 112 insertions(+), 103 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bbc141545..4099613db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ ### 🔧 Internal changes +- Refactored the `Courses` table to `Course` with a database migration + ## [0.8.0] - 2026-06-09 ### ✨ New features/enhancements diff --git a/app/Controllers/Course.hs b/app/Controllers/Course.hs index 6921be3b1..ab0333ed2 100644 --- a/app/Controllers/Course.hs +++ b/app/Controllers/Course.hs @@ -6,7 +6,7 @@ import Control.Monad.IO.Class (liftIO) import qualified Data.Text as T (Text, unlines) import Database.Persist (Entity) import Database.Persist.Sqlite (SqlPersistM, entityVal, selectList) -import Database.Tables as Tables (Courses, coursesCode) +import Database.Tables as Tables (Course, courseCode) import Happstack.Server (Response, ServerPart, lookText', notFound, ok, toResponse) import Models.Course (getDeptCourses, returnCourse) import Util.Happstack (createJSONResponse) @@ -25,8 +25,8 @@ retrieveCourse = do index :: ServerPart Response index = do response <- liftIO $ runDb $ do - coursesList :: [Entity Courses] <- selectList [] [] - let codes = map (coursesCode . entityVal) coursesList + coursesList :: [Entity Course] <- selectList [] [] + let codes = map (courseCode . entityVal) coursesList return $ T.unlines codes :: SqlPersistM T.Text return $ toResponse response diff --git a/app/Database/CourseVideoSeed.hs b/app/Database/CourseVideoSeed.hs index ba5f77367..693e40d7b 100644 --- a/app/Database/CourseVideoSeed.hs +++ b/app/Database/CourseVideoSeed.hs @@ -24,7 +24,7 @@ courseVideos = [ seedVideo :: (Text, [Text]) -> SqlPersistM () seedVideo (code, videos) = - updateWhere [CoursesCode ==. code] [CoursesVideoUrls =. videos] + updateWhere [CourseCode ==. code] [CourseVideoUrls =. videos] -- | Sets the video routes of all course rows. seedVideos :: IO () diff --git a/app/Database/Migrations.hs b/app/Database/Migrations.hs index 1ac16ed00..bf27c6373 100644 --- a/app/Database/Migrations.hs +++ b/app/Database/Migrations.hs @@ -31,7 +31,9 @@ applyMigrations currVersion migrations = do -- | List of migrations migrationList :: [MigrationWrapper] -migrationList = [MigrationWrapper {version=2, script=renamePostTables}] +migrationList = [ MigrationWrapper {version=2, script=renamePostTables} + , MigrationWrapper {version=3, script=renameCoursesTable} + ] -- | Migration script which renames the Post tables to Program renamePostTables :: Migration @@ -40,6 +42,11 @@ renamePostTables = do addMigration True "ALTER TABLE post_category RENAME TO program_category;" addMigration True "ALTER TABLE program_category RENAME COLUMN post TO program;" +-- | Migration script which renames the Courses table to Course +renameCoursesTable :: Migration +renameCoursesTable = + addMigration True "ALTER TABLE courses RENAME TO course;" + -- | Gets the current version of the database. -- If no version is defined, initialize the -- version to the latest version and return that. diff --git a/app/Database/Tables.hs b/app/Database/Tables.hs index 75431190d..7a53c8610 100644 --- a/app/Database/Tables.hs +++ b/app/Database/Tables.hs @@ -19,8 +19,8 @@ straightforward. module Database.Tables where -import Data.Aeson (FromJSON (parseJSON), ToJSON (toJSON), genericToJSON, withObject, - (.!=), (.:), (.:?)) +import Data.Aeson (FromJSON (parseJSON), ToJSON (toJSON), genericToJSON, withObject, (.!=), (.:), + (.:?)) import Data.Aeson.Types (Options (..), Parser, Value (Object), defaultOptions) import Data.Char (toLower) import qualified Data.Text as T @@ -43,7 +43,7 @@ Department json Primary name UniqueName name -Courses +Course code T.Text Primary code title T.Text Maybe diff --git a/app/Export/GetImages.hs b/app/Export/GetImages.hs index 61afd80b0..d8bcee43c 100644 --- a/app/Export/GetImages.hs +++ b/app/Export/GetImages.hs @@ -17,7 +17,7 @@ import qualified Data.Map as M import Data.Maybe (fromMaybe) import qualified Data.Text as T import qualified Data.Text.Lazy.IO as LTIO -import Database.Tables as Tables +import Database.Tables (Time (..)) import Export.ImageConversion (withImageFile) import Export.TimetableImageCreator (renderTableHelper, times) import Models.Meeting (getMeetingTime) diff --git a/app/Models/Course.hs b/app/Models/Course.hs index 9ce303f69..480d1267b 100644 --- a/app/Models/Course.hs +++ b/app/Models/Course.hs @@ -17,16 +17,16 @@ import Database.Persist.Class (selectKeysList) import Database.Persist.Sqlite (Entity, PersistValue (PersistText), SqlPersistM, entityVal, get, insert_, rawSql, selectFirst, selectList, (<-.), (==.)) import Database.Tables (Breadth (breadthDescription), - Courses (coursesBreadth, coursesCode, coursesCoreqs, coursesDescription, coursesDistribution, coursesExclusions, coursesPrereqString, coursesTitle, coursesVideoUrls), + Course (courseBreadth, courseCode, courseCoreqs, courseDescription, courseDistribution, courseExclusions, coursePrereqString, courseTitle, courseVideoUrls), Distribution (distributionDescription), - EntityField (BreadthDescription, CoursesCode, DistributionDescription, MeetingCode), + EntityField (BreadthDescription, CourseCode, DistributionDescription, MeetingCode), Key, MeetTime', Meeting (meetingCode)) import GHC.Generics (Generic) import Models.Meeting (buildMeetTimes, meetingQuery) -- | The data for a single course, as returned by the back-end to the front-end. --- This is different from the schema-defined 'Courses' type (in "Database.Tables") --- 'Courses' describes how a course is stored in the database, whereas +-- This is different from the schema-defined 'Course' type (in "Database.Tables") +-- 'Course' describes how a course is stored in the database, whereas -- 'CourseData' describes the shape of the information sent to the client -- when a course is requested. data CourseData = @@ -51,7 +51,7 @@ returnCourse lowerStr = runDb $ do let courseStr = T.toUpper lowerStr -- TODO: require the client to pass the full course code let fullCodes = [courseStr, T.append courseStr "H1", T.append courseStr "Y1"] - sqlCourse :: (Maybe (Entity Courses)) <- selectFirst [CoursesCode <-. fullCodes] [] + sqlCourse :: (Maybe (Entity Course)) <- selectFirst [CourseCode <-. fullCodes] [] case sqlCourse of Nothing -> return Nothing Just course -> do @@ -73,48 +73,48 @@ getDescriptionD (Just key) = do maybeDistribution <- get key return $ fmap distributionDescription maybeDistribution --- | Builds a 'CourseData' structure from a tuple from the Courses table. +-- | Builds a 'CourseData' structure from a tuple from the Course table. -- Some fields still need to be added in. -buildCourse :: [MeetTime'] -> Courses -> SqlPersistM CourseData +buildCourse :: [MeetTime'] -> Course -> SqlPersistM CourseData buildCourse allMeetings course = do - cBreadth <- getDescriptionB (coursesBreadth course) - cDistribution <- getDescriptionD (coursesDistribution course) + cBreadth <- getDescriptionB (courseBreadth course) + cDistribution <- getDescriptionD (courseDistribution course) return $ CourseData cBreadth -- TODO: Remove the filter and allow double-quotes - (fmap (T.filter (/='\"')) (coursesDescription course)) - (fmap (T.filter (/='\"')) (coursesTitle course)) - (coursesPrereqString course) + (fmap (T.filter (/='\"')) (courseDescription course)) + (fmap (T.filter (/='\"')) (courseTitle course)) + (coursePrereqString course) (Just allMeetings) - (coursesCode course) - (coursesExclusions course) + (courseCode course) + (courseExclusions course) cDistribution - (coursesCoreqs course) - (coursesVideoUrls course) + (courseCoreqs course) + (courseVideoUrls course) -- | Retrieves the prerequisites for a course (code) as a string. -- Also retrieves the actual course code in the database in case -- the one the user inputs doesn't match it exactly prereqsForCourse :: T.Text -> IO (Either String (T.Text, T.Text)) -prereqsForCourse courseCode = runDb $ do - let upperCaseCourseCode = T.toUpper courseCode - course <- selectFirst [CoursesCode <-. [upperCaseCourseCode, upperCaseCourseCode `T.append` "H1", upperCaseCourseCode `T.append` "Y1"]] [] +prereqsForCourse code = runDb $ do + let upperCaseCourseCode = T.toUpper code + course <- selectFirst [CourseCode <-. [upperCaseCourseCode, upperCaseCourseCode `T.append` "H1", upperCaseCourseCode `T.append` "Y1"]] [] case course of Nothing -> return (Left "Course not found") Just courseEntity -> return (Right - (coursesCode $ entityVal courseEntity, - fromMaybe "" $ coursesPrereqString $ entityVal courseEntity) + (courseCode $ entityVal courseEntity, + fromMaybe "" $ coursePrereqString $ entityVal courseEntity) ) :: SqlPersistM (Either String (T.Text, T.Text)) getDeptCourses :: MonadIO m => T.Text -> m [CourseData] getDeptCourses dept = liftIO $ runDb $ do - courses :: [Entity Courses] <- rawSql "SELECT ?? FROM courses WHERE code LIKE ?" [PersistText $ T.snoc dept '%'] + courses :: [Entity Course] <- rawSql "SELECT ?? FROM course WHERE code LIKE ?" [PersistText $ T.snoc dept '%'] let deptCourses = map entityVal courses - meetings :: [Entity Meeting] <- selectList [MeetingCode <-. map coursesCode deptCourses] [] + meetings :: [Entity Meeting] <- selectList [MeetingCode <-. map courseCode deptCourses] [] mapM (processCourse meetings) deptCourses where processCourse allMeetings course = do - let courseMeetings = filter (\m -> meetingCode (entityVal m) == coursesCode course) allMeetings + let courseMeetings = filter (\m -> meetingCode (entityVal m) == courseCode course) allMeetings allTimes <- mapM buildMeetTimes courseMeetings buildCourse allTimes course @@ -138,13 +138,13 @@ getBreadthKey description_ = do [] -> Nothing (x:_) -> Just x --- | Inserts course into the Courses table. -insertCourse :: (Courses, T.Text, T.Text) -> SqlPersistM () +-- | Inserts course into the Course table. +insertCourse :: (Course, T.Text, T.Text) -> SqlPersistM () insertCourse (course, breadthDesc, distributionDesc) = do - maybeCourse <- selectFirst [CoursesCode ==. coursesCode course] [] + maybeCourse <- selectFirst [CourseCode ==. courseCode course] [] breadthKey <- getBreadthKey breadthDesc distributionKey <- getDistributionKey distributionDesc case maybeCourse of - Nothing -> insert_ $ course {coursesBreadth = breadthKey, - coursesDistribution = distributionKey} + Nothing -> insert_ $ course {courseBreadth = breadthKey, + courseDistribution = distributionKey} Just _ -> return () diff --git a/app/WebParsing/ArtSciParser.hs b/app/WebParsing/ArtSciParser.hs index 74f5b36ab..a9c197f23 100644 --- a/app/WebParsing/ArtSciParser.hs +++ b/app/WebParsing/ArtSciParser.hs @@ -10,7 +10,7 @@ import Data.Text.Lazy (toStrict) import Data.Text.Lazy.Encoding (decodeUtf8) import Database.Persist (insertUnique) import Database.Persist.Sqlite (SqlPersistM) -import Database.Tables (Courses (..), Department (..)) +import Database.Tables (Course (..), Department (..)) import Models.Building (parseBuildings) import Models.Course (insertCourse) import Network.HTTP.Simple (getResponseBody, httpLBS, parseRequest) @@ -89,7 +89,7 @@ parsePrograms programs = mapM_ addPostToDatabase $ TS.partitions isAccordionHead isAccordionHeader = tagOpenAttrNameLit "h3" "class" (T.isInfixOf "js-views-accordion-group-header") -- | Parse the section of the course calendar listing the courses offered by a department. -parseCourses :: [Tag T.Text] -> [(Courses, T.Text, T.Text)] +parseCourses :: [Tag T.Text] -> [(Course, T.Text, T.Text)] parseCourses tags = let elems = TS.partitions isAccordion tags courses = map parseCourse elems @@ -98,7 +98,7 @@ parseCourses tags = where isAccordion = tagOpenAttrNameLit "h3" "class" (T.isInfixOf "js-views-accordion-group-header") - parseCourse :: [Tag T.Text] -> (Courses, T.Text, T.Text) + parseCourse :: [Tag T.Text] -> (Course, T.Text, T.Text) parseCourse courseTags = let courseHeader = T.strip . TS.innerText $ takeWhile (not . TS.isTagCloseName "h3") courseTags (code, title) = either (error . show) id $ parse parseCourseTitle "course title" courseHeader @@ -116,17 +116,17 @@ parseCourses tags = distribution = fromMaybe "" $ getValue "Distribution Requirements:" courseContents breadth = fromMaybe "" $ getValue "Breadth Requirements:" courseContents in - (Courses code - (Just title) - (Just description) - (fmap (T.pack . show . parseReqs . T.unpack) prereqString) - exclusion - Nothing - Nothing - prereqString - coreq - [], - breadth, distribution) + (Course code + (Just title) + (Just description) + (fmap (T.pack . show . parseReqs . T.unpack) prereqString) + exclusion + Nothing + Nothing + prereqString + coreq + [], + breadth, distribution) getValue label texts = do i <- findIndex (T.isPrefixOf label) texts diff --git a/backend-test/Controllers/CourseControllerTests.hs b/backend-test/Controllers/CourseControllerTests.hs index 8e904165f..cdabd5aa4 100644 --- a/backend-test/Controllers/CourseControllerTests.hs +++ b/backend-test/Controllers/CourseControllerTests.hs @@ -18,7 +18,7 @@ import qualified Data.Map as Map import Data.Maybe (fromMaybe, mapMaybe) import qualified Data.Text as T import Database.Persist.Sqlite (SqlPersistM, insert, insertMany_, insert_) -import Database.Tables (Building (..), Courses (..), MeetTime (..), Meeting (..), Time' (..)) +import Database.Tables (Building (..), Course (..), MeetTime (..), Meeting (..), Time' (..)) import Happstack.Server (rsBody, rsCode) import Models.Time (buildTimes) import Test.Tasty (TestTree) @@ -198,17 +198,17 @@ runRetrieveCourseTest (label, courseName, courseData, meetingTimes, expectedCode Nothing -> [] let courseToInsert = - Courses - { coursesCode = currCourseName - , coursesTitle = Map.lookup "title" courseData - , coursesDescription = Map.lookup "description" courseData - , coursesPrereqs = Map.lookup "prereqs" courseData - , coursesExclusions = Map.lookup "exclusions" courseData - , coursesBreadth = Nothing - , coursesDistribution = Nothing - , coursesPrereqString = Map.lookup "prereqString" courseData - , coursesCoreqs = Map.lookup "coreqs" courseData - , coursesVideoUrls = videoUrls + Course + { courseCode = currCourseName + , courseTitle = Map.lookup "title" courseData + , courseDescription = Map.lookup "description" courseData + , coursePrereqs = Map.lookup "prereqs" courseData + , courseExclusions = Map.lookup "exclusions" courseData + , courseBreadth = Nothing + , courseDistribution = Nothing + , coursePrereqString = Map.lookup "prereqString" courseData + , courseCoreqs = Map.lookup "coreqs" courseData + , courseVideoUrls = videoUrls } let buildingCodes = getUniqueBuildings meetingTimes @@ -237,7 +237,7 @@ runRetrieveCourseTests = map runRetrieveCourseTest retrieveCourseTestCases insertCourses :: [T.Text] -> SqlPersistM () insertCourses = mapM_ insertCourse where - insertCourse code = insert_ (Courses code Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing []) + insertCourse code = insert_ (Course code Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing []) -- | Helper function to insert MeetTimes into the database insertMeetingTimes :: [MeetTime] -> SqlPersistM () @@ -284,7 +284,7 @@ runIndexTests :: [TestTree] runIndexTests = map runIndexTest indexTestCases -- | List of test cases as (case, database state, input [dept], expected JSON output) for the courseInfo function -courseInfoTestCases :: [(String, [Courses], T.Text, String)] +courseInfoTestCases :: [(String, [Course], T.Text, String)] courseInfoTestCases = [ ("Empty Database" , [] @@ -308,45 +308,45 @@ courseInfoTestCases = , "[{\"allMeetingTimes\":[],\"breadth\":null,\"coreqs\":null,\"description\":\"Programming in a language such as Python. Elementary data types, lists, maps. Program structure: control flow, functions, classes, objects, methods. Algorithms and problem solving. Searching, sorting, and complexity. Unit testing. Floating-point numbers and numerical computation. No prior programming experience required.\",\"distribution\":null,\"exclusions\":\"CSC110Y1, CSC111H1, CSC120H1, CSC121H1, CSC148H1, CSC108H5, CSC148H5, CSCA08H3, CSCA20H3, CSCA48H3\",\"name\":\"CSC108H1\",\"prereqString\":null,\"title\":\"Introduction to Computer Programming\",\"videoUrls\":[]},{\"allMeetingTimes\":[],\"breadth\":null,\"coreqs\":\"( CSC108H1/ equivalent programming experience)/ CSC110Y1/ CSC148H1 *Note: the corequisite may be completed either concurrently or in advance.\",\"description\":\"An introduction to probability using simulation and mathematical frameworks, with emphasis on the probability needed for more advanced study in statistical practice. Topics covered include probability spaces, random variables, discrete and continuous probability distributions, probability mass, density, and distribution functions, expectation and variance, independence, conditional probability, the law of large numbers, the central limit theorem, sampling distributions. Computer simulation will be taught and used extensively for calculations and to guide the theoretical development.\",\"distribution\":null,\"exclusions\":\"STA247H1, STA201H1, STA255H1, STA257H1, ECO227Y1, MAT370H1, STAB52H3, STA256H5, ECO227Y5\",\"name\":\"STA237H1\",\"prereqString\":\"( MAT135H1, MAT136H1)/ MAT137Y1/ MAT157Y1/ ( MATA30H3, MATA36H3)/ ( MATA31H3, MATA37H3)/ ( MAT135H5, MAT136H5)/ MAT137Y5/ MAT157Y5/ ( MAT137H5, MAT139H5)/ ( MAT157H5, MAT159H5)\",\"title\":\"Probability, Statistics and Data Analysis I\",\"videoUrls\":[]},{\"allMeetingTimes\":[],\"breadth\":null,\"coreqs\":\"CSC108H1/ CSC110Y1/ CSC148H1 *Note: the corequisite may be completed either concurrently or in advance.\",\"description\":\"An introduction to statistical inference and practice. Statistical models and parameters, estimators of parameters and their statistical properties, methods of estimation, confidence intervals, hypothesis testing, likelihood function, the linear model. Use of statistical computation for data analysis and simulation.\",\"distribution\":null,\"exclusions\":\"ECO220Y1/ ECO227Y1/ GGR270H1/ PSY201H1/ SOC300H1/ SOC202H1/ SOC252H1/ STA220H1/ STA221H1/ STA255H1/ STA248H1/ STA261H1/ STA288H1/ EEB225H1/ STAB22H3/ STAB27H3/ STAB57H3/ STA220H5/ STA221H5/ STA258H5/ STA260H5/ ECO220Y5/ ECO227Y5\",\"name\":\"STA238H1\",\"prereqString\":\"STA237H1/ STA247H1/ STA257H1/ STAB52H3/ STA256H5\",\"title\":\"Probability, Statistics and Data Analysis II\",\"videoUrls\":[\"[https://example.com/video1\",\"https://example.com/video2]\"]}]") ] where - sta237 = Courses - { coursesCode = "STA237H1" - , coursesTitle = Just "Probability, Statistics and Data Analysis I" - , coursesDescription = Just "An introduction to probability using simulation and mathematical frameworks, with emphasis on the probability needed for more advanced study in statistical practice. Topics covered include probability spaces, random variables, discrete and continuous probability distributions, probability mass, density, and distribution functions, expectation and variance, independence, conditional probability, the law of large numbers, the central limit theorem, sampling distributions. Computer simulation will be taught and used extensively for calculations and to guide the theoretical development." - , coursesPrereqs = Just "( MAT135H1, MAT136H1)/ MAT137Y1/ MAT157Y1/ ( MATA30H3, MATA36H3)/ ( MATA31H3, MATA37H3)/ ( MAT135H5, MAT136H5)/ MAT137Y5/ MAT157Y5/ ( MAT137H5, MAT139H5)/ ( MAT157H5, MAT159H5)" - , coursesExclusions = Just "STA247H1, STA201H1, STA255H1, STA257H1, ECO227Y1, MAT370H1, STAB52H3, STA256H5, ECO227Y5" - , coursesBreadth = Nothing - , coursesDistribution = Nothing - , coursesPrereqString = Just "( MAT135H1, MAT136H1)/ MAT137Y1/ MAT157Y1/ ( MATA30H3, MATA36H3)/ ( MATA31H3, MATA37H3)/ ( MAT135H5, MAT136H5)/ MAT137Y5/ MAT157Y5/ ( MAT137H5, MAT139H5)/ ( MAT157H5, MAT159H5)" - , coursesCoreqs = Just "( CSC108H1/ equivalent programming experience)/ CSC110Y1/ CSC148H1 *Note: the corequisite may be completed either concurrently or in advance." - , coursesVideoUrls = [] + sta237 = Course + { courseCode = "STA237H1" + , courseTitle = Just "Probability, Statistics and Data Analysis I" + , courseDescription = Just "An introduction to probability using simulation and mathematical frameworks, with emphasis on the probability needed for more advanced study in statistical practice. Topics covered include probability spaces, random variables, discrete and continuous probability distributions, probability mass, density, and distribution functions, expectation and variance, independence, conditional probability, the law of large numbers, the central limit theorem, sampling distributions. Computer simulation will be taught and used extensively for calculations and to guide the theoretical development." + , coursePrereqs = Just "( MAT135H1, MAT136H1)/ MAT137Y1/ MAT157Y1/ ( MATA30H3, MATA36H3)/ ( MATA31H3, MATA37H3)/ ( MAT135H5, MAT136H5)/ MAT137Y5/ MAT157Y5/ ( MAT137H5, MAT139H5)/ ( MAT157H5, MAT159H5)" + , courseExclusions = Just "STA247H1, STA201H1, STA255H1, STA257H1, ECO227Y1, MAT370H1, STAB52H3, STA256H5, ECO227Y5" + , courseBreadth = Nothing + , courseDistribution = Nothing + , coursePrereqString = Just "( MAT135H1, MAT136H1)/ MAT137Y1/ MAT157Y1/ ( MATA30H3, MATA36H3)/ ( MATA31H3, MATA37H3)/ ( MAT135H5, MAT136H5)/ MAT137Y5/ MAT157Y5/ ( MAT137H5, MAT139H5)/ ( MAT157H5, MAT159H5)" + , courseCoreqs = Just "( CSC108H1/ equivalent programming experience)/ CSC110Y1/ CSC148H1 *Note: the corequisite may be completed either concurrently or in advance." + , courseVideoUrls = [] } - sta238 = Courses - { coursesCode = "STA238H1" - , coursesTitle = Just "Probability, Statistics and Data Analysis II" - , coursesDescription = Just "An introduction to statistical inference and practice. Statistical models and parameters, estimators of parameters and their statistical properties, methods of estimation, confidence intervals, hypothesis testing, likelihood function, the linear model. Use of statistical computation for data analysis and simulation." - , coursesPrereqs = Just "STA237H1/ STA247H1/ STA257H1/ STAB52H3/ STA256H5" - , coursesExclusions = Just "ECO220Y1/ ECO227Y1/ GGR270H1/ PSY201H1/ SOC300H1/ SOC202H1/ SOC252H1/ STA220H1/ STA221H1/ STA255H1/ STA248H1/ STA261H1/ STA288H1/ EEB225H1/ STAB22H3/ STAB27H3/ STAB57H3/ STA220H5/ STA221H5/ STA258H5/ STA260H5/ ECO220Y5/ ECO227Y5" - , coursesBreadth = Nothing - , coursesDistribution = Nothing - , coursesPrereqString = Just "STA237H1/ STA247H1/ STA257H1/ STAB52H3/ STA256H5" - , coursesCoreqs = Just "CSC108H1/ CSC110Y1/ CSC148H1 *Note: the corequisite may be completed either concurrently or in advance." - , coursesVideoUrls = ["[https://example.com/video1", "https://example.com/video2]"] + sta238 = Course + { courseCode = "STA238H1" + , courseTitle = Just "Probability, Statistics and Data Analysis II" + , courseDescription = Just "An introduction to statistical inference and practice. Statistical models and parameters, estimators of parameters and their statistical properties, methods of estimation, confidence intervals, hypothesis testing, likelihood function, the linear model. Use of statistical computation for data analysis and simulation." + , coursePrereqs = Just "STA237H1/ STA247H1/ STA257H1/ STAB52H3/ STA256H5" + , courseExclusions = Just "ECO220Y1/ ECO227Y1/ GGR270H1/ PSY201H1/ SOC300H1/ SOC202H1/ SOC252H1/ STA220H1/ STA221H1/ STA255H1/ STA248H1/ STA261H1/ STA288H1/ EEB225H1/ STAB22H3/ STAB27H3/ STAB57H3/ STA220H5/ STA221H5/ STA258H5/ STA260H5/ ECO220Y5/ ECO227Y5" + , courseBreadth = Nothing + , courseDistribution = Nothing + , coursePrereqString = Just "STA237H1/ STA247H1/ STA257H1/ STAB52H3/ STA256H5" + , courseCoreqs = Just "CSC108H1/ CSC110Y1/ CSC148H1 *Note: the corequisite may be completed either concurrently or in advance." + , courseVideoUrls = ["[https://example.com/video1", "https://example.com/video2]"] } - csc108 = Courses - { coursesCode = "CSC108H1" - , coursesTitle = Just "Introduction to Computer Programming" - , coursesDescription = Just "Programming in a language such as Python. Elementary data types, lists, maps. Program structure: control flow, functions, classes, objects, methods. Algorithms and problem solving. Searching, sorting, and complexity. Unit testing. Floating-point numbers and numerical computation. No prior programming experience required." - , coursesPrereqs = Nothing - , coursesExclusions = Just "CSC110Y1, CSC111H1, CSC120H1, CSC121H1, CSC148H1, CSC108H5, CSC148H5, CSCA08H3, CSCA20H3, CSCA48H3" - , coursesBreadth = Nothing - , coursesDistribution = Nothing - , coursesPrereqString = Nothing - , coursesCoreqs = Nothing - , coursesVideoUrls = [] + csc108 = Course + { courseCode = "CSC108H1" + , courseTitle = Just "Introduction to Computer Programming" + , courseDescription = Just "Programming in a language such as Python. Elementary data types, lists, maps. Program structure: control flow, functions, classes, objects, methods. Algorithms and problem solving. Searching, sorting, and complexity. Unit testing. Floating-point numbers and numerical computation. No prior programming experience required." + , coursePrereqs = Nothing + , courseExclusions = Just "CSC110Y1, CSC111H1, CSC120H1, CSC121H1, CSC148H1, CSC108H5, CSC148H5, CSCA08H3, CSCA20H3, CSCA48H3" + , courseBreadth = Nothing + , courseDistribution = Nothing + , coursePrereqString = Nothing + , courseCoreqs = Nothing + , courseVideoUrls = [] } -- | Run a test case (case, database state, input [dept], expected JSON output) on the courseInfo function -runCourseInfoTest :: (String, [Courses], T.Text, String) -> TestTree +runCourseInfoTest :: (String, [Course], T.Text, String) -> TestTree runCourseInfoTest (label, state, dept, expected) = testCase label $ do runDb $ do diff --git a/backend-test/Controllers/GenerateControllerTests.hs b/backend-test/Controllers/GenerateControllerTests.hs index 12cea2aed..3091b9345 100644 --- a/backend-test/Controllers/GenerateControllerTests.hs +++ b/backend-test/Controllers/GenerateControllerTests.hs @@ -18,7 +18,7 @@ import qualified Data.ByteString.Lazy as BSL import Data.Foldable (toList) import qualified Data.Text as T import Database.Persist.Sqlite (SqlPersistM, insert_) -import Database.Tables (Courses (..)) +import Database.Tables (Course (..)) import Happstack.Server (rsBody) import Test.Tasty (TestTree) import Test.Tasty.HUnit (assertEqual, testCase) @@ -28,7 +28,7 @@ import TestHelpers (clearDatabase, mockPutRequest, runServerPartWith, withDataba insertCoursesWithPrerequisites :: [(T.Text, Maybe T.Text)] -> SqlPersistM () insertCoursesWithPrerequisites = mapM_ insertCourse where - insertCourse (code, prereqString) = insert_ (Courses { coursesCode = code, coursesTitle = Nothing, coursesDescription = Nothing, coursesPrereqs = prereqString, coursesExclusions = Nothing, coursesBreadth = Nothing, coursesDistribution = Nothing, coursesPrereqString = prereqString, coursesCoreqs = Nothing, coursesVideoUrls = [] }) + insertCourse (code, prereqString) = insert_ (Course { courseCode = code, courseTitle = Nothing, courseDescription = Nothing, coursePrereqs = prereqString, courseExclusions = Nothing, courseBreadth = Nothing, courseDistribution = Nothing, coursePrereqString = prereqString, courseCoreqs = Nothing, courseVideoUrls = [] }) -- | List of test cases as -- (input course, course/prereq structure, JSON payload, expected # of nodes in prereq graph, expected # of boolean nodes in prereq graph) diff --git a/backend-test/TestHelpers.hs b/backend-test/TestHelpers.hs index 559432001..c3d75894c 100644 --- a/backend-test/TestHelpers.hs +++ b/backend-test/TestHelpers.hs @@ -97,7 +97,7 @@ runServerPart sp = runServerPartWith sp (mockGetRequest "/" [] "") clearDatabase :: SqlPersistM () clearDatabase = do deleteWhere ([] :: [Filter Department]) - deleteWhere ([] :: [Filter Courses]) + deleteWhere ([] :: [Filter Course]) deleteWhere ([] :: [Filter Times]) deleteWhere ([] :: [Filter Meeting]) deleteWhere ([] :: [Filter Breadth]) From 054afb9d00dfa489143512c590d060225ef8be37 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 19 Jun 2026 15:15:27 -0400 Subject: [PATCH 31/39] build(deps): bump launch-editor from 2.11.1 to 2.14.1 (#1733) Bumps [launch-editor](https://github.com/vitejs/launch-editor) from 2.11.1 to 2.14.1. - [Commits](https://github.com/vitejs/launch-editor/compare/v2.11.1...v2.14.1) --- updated-dependencies: - dependency-name: launch-editor dependency-version: 2.14.1 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/yarn.lock b/yarn.lock index b5719f86d..839ef29ea 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8990,12 +8990,12 @@ __metadata: linkType: hard "launch-editor@npm:^2.6.1": - version: 2.11.1 - resolution: "launch-editor@npm:2.11.1" + version: 2.14.1 + resolution: "launch-editor@npm:2.14.1" dependencies: picocolors: ^1.1.1 - shell-quote: ^1.8.3 - checksum: 95a2e0a50ce15425a87fd035bdef2de37e13c2aee9cd62756783efb286a6e36a341cfcbaecb0d578131a5411c6a1c74c422f9c5b6cb6f4c8284d6078967e08b4 + shell-quote: ^1.8.4 + checksum: 232ea8a80146e7fec6c8ece7ebb600d58a82e9938f36111194980188d276935f424754b18e37d5b098f596d30580def723b231e093c27c3bcd703418278afc4c languageName: node linkType: hard @@ -11456,7 +11456,7 @@ __metadata: languageName: node linkType: hard -"shell-quote@npm:^1.8.3": +"shell-quote@npm:^1.8.4": version: 1.8.4 resolution: "shell-quote@npm:1.8.4" checksum: 082dc836baa8ade01144ee3068af487ea45ba570ea6ab13a5eddc11ab16a976b8857b51ef2caf7dc9a1e173ff0aea685b8f78b4f6f5a0a1ef24c7b17c51350e2 From 2a568d46708d8f2eafff8a52b1f8cd9a5ce455ee Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 21 Jun 2026 16:37:26 -0400 Subject: [PATCH 32/39] build(deps-dev): bump webpack-dev-server from 5.2.4 to 5.2.5 (#1734) Bumps [webpack-dev-server](https://github.com/webpack/webpack-dev-server) from 5.2.4 to 5.2.5. - [Release notes](https://github.com/webpack/webpack-dev-server/releases) - [Changelog](https://github.com/webpack/webpack-dev-server/blob/main/CHANGELOG.md) - [Commits](https://github.com/webpack/webpack-dev-server/compare/v5.2.4...v5.2.5) --- updated-dependencies: - dependency-name: webpack-dev-server dependency-version: 5.2.5 dependency-type: direct:development ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 29b381b11..5db411f7a 100644 --- a/package.json +++ b/package.json @@ -87,7 +87,7 @@ "stylelint-config-standard-scss": "^17.0.0", "webpack": "^5.105.3", "webpack-cli": "^6.0.1", - "webpack-dev-server": "^5.2.4", + "webpack-dev-server": "^5.2.5", "webpack-merge": "^6.0.1" }, "packageManager": "yarn@3.3.1", diff --git a/yarn.lock b/yarn.lock index 839ef29ea..221d42581 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5342,7 +5342,7 @@ __metadata: stylelint-config-standard-scss: ^17.0.0 webpack: ^5.105.3 webpack-cli: ^6.0.1 - webpack-dev-server: ^5.2.4 + webpack-dev-server: ^5.2.5 webpack-merge: ^6.0.1 languageName: unknown linkType: soft @@ -12857,9 +12857,9 @@ __metadata: languageName: node linkType: hard -"webpack-dev-server@npm:^5.2.4": - version: 5.2.4 - resolution: "webpack-dev-server@npm:5.2.4" +"webpack-dev-server@npm:^5.2.5": + version: 5.2.5 + resolution: "webpack-dev-server@npm:5.2.5" dependencies: "@types/bonjour": ^3.5.13 "@types/connect-history-api-fallback": ^1.5.4 @@ -12898,7 +12898,7 @@ __metadata: optional: true bin: webpack-dev-server: bin/webpack-dev-server.js - checksum: 4e1b13dc170b9964e579e5703dd56e97c2fbb6b101586cfda56f58f1ea0327ea9fcb9e4f36ff6264ee02ab69298697df87bd9617716d9c8379d2a6dc22bb103f + checksum: 349719d0487a5672f65a7427d54afc9f8ddc6b695042641ed9f468cb5a3c90866e16a236ecdb2ac62d2a922712f9c1296b8805b7ec0880f6a3f5c4280785f200 languageName: node linkType: hard From fca390671e5fc5a4c96239de8358b0552cc66140 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 21 Jun 2026 16:39:26 -0400 Subject: [PATCH 33/39] build(deps): bump form-data from 4.0.4 to 4.0.6 (#1735) Bumps [form-data](https://github.com/form-data/form-data) from 4.0.4 to 4.0.6. - [Changelog](https://github.com/form-data/form-data/blob/master/CHANGELOG.md) - [Commits](https://github.com/form-data/form-data/compare/v4.0.4...v4.0.6) --- updated-dependencies: - dependency-name: form-data dependency-version: 4.0.6 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/yarn.lock b/yarn.lock index 221d42581..0c0ad5b53 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6843,15 +6843,15 @@ __metadata: linkType: hard "form-data@npm:~4.0.4": - version: 4.0.4 - resolution: "form-data@npm:4.0.4" + version: 4.0.6 + resolution: "form-data@npm:4.0.6" dependencies: asynckit: ^0.4.0 combined-stream: ^1.0.8 es-set-tostringtag: ^2.1.0 - hasown: ^2.0.2 - mime-types: ^2.1.12 - checksum: 9b7788836df9fa5a6999e0c02515b001946b2a868cfe53f026c69e2c537a2ff9fbfb8e9d2b678744628f3dc7a2d6e14e4e45dfaf68aa6239727f0bdb8ce0abf2 + hasown: ^2.0.4 + mime-types: ^2.1.35 + checksum: e51b9e97678c250c872cd4ec3e5eaa8fa43bee4b1acf8274c337308aebc6aebb0553091ce0810612826601ffafed9dace12504a63c6ef16c57fffcd7dcfec457 languageName: node linkType: hard @@ -7327,6 +7327,15 @@ __metadata: languageName: node linkType: hard +"hasown@npm:^2.0.4": + version: 2.0.4 + resolution: "hasown@npm:2.0.4" + dependencies: + function-bind: ^1.1.2 + checksum: 4bd8f916b629e06324853593ffbdd45e200022952a85ad0c967f3bd4c2e4c7e1f9a9766fbe6186f60bd394e0afc73e719730caa1da15cd9bd832b7cdf53fd26c + languageName: node + linkType: hard + "hoist-non-react-statics@npm:^3.3.0, hoist-non-react-statics@npm:^3.3.1": version: 3.3.2 resolution: "hoist-non-react-statics@npm:3.3.2" @@ -9442,7 +9451,7 @@ __metadata: languageName: node linkType: hard -"mime-types@npm:^2.1.12, mime-types@npm:^2.1.27, mime-types@npm:^2.1.31, mime-types@npm:~2.1.17, mime-types@npm:~2.1.19, mime-types@npm:~2.1.24, mime-types@npm:~2.1.34": +"mime-types@npm:^2.1.27, mime-types@npm:^2.1.31, mime-types@npm:^2.1.35, mime-types@npm:~2.1.17, mime-types@npm:~2.1.19, mime-types@npm:~2.1.24, mime-types@npm:~2.1.34": version: 2.1.35 resolution: "mime-types@npm:2.1.35" dependencies: From 112ebfb628de575174ef79f8b88b298cafd812f6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 21 Jun 2026 16:40:35 -0400 Subject: [PATCH 34/39] build(deps): bump tar from 7.5.11 to 7.5.16 (#1736) Bumps [tar](https://github.com/isaacs/node-tar) from 7.5.11 to 7.5.16. - [Release notes](https://github.com/isaacs/node-tar/releases) - [Changelog](https://github.com/isaacs/node-tar/blob/main/CHANGELOG.md) - [Commits](https://github.com/isaacs/node-tar/compare/v7.5.11...v7.5.16) --- updated-dependencies: - dependency-name: tar dependency-version: 7.5.16 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 0c0ad5b53..a70a3048b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12179,15 +12179,15 @@ __metadata: linkType: hard "tar@npm:^7.4.3": - version: 7.5.11 - resolution: "tar@npm:7.5.11" + version: 7.5.16 + resolution: "tar@npm:7.5.16" dependencies: "@isaacs/fs-minipass": ^4.0.0 chownr: ^3.0.0 minipass: ^7.1.2 minizlib: ^3.1.0 yallist: ^5.0.0 - checksum: 7f6785a85dd571b88985e493ec86f692962cbfa7b4017961fddfd2241e0ff3bcd89ed347f4c02b5433aa22b30cca5566e8711543df054fda8fd12425f505378f + checksum: 9b7f886f5ce8681a7430f80b9b377bfa498e6feb957b9afe6507db08e59d309f8546b7f76a0c2e47bdb54da4602575a5c7519e287fe94de8302e635032fc94f1 languageName: node linkType: hard From 5b8463c56f52ed6331c72c54fb65b9f5e5b4d703 Mon Sep 17 00:00:00 2001 From: Angelina Jiang <43974738+AngelsandDevsLOL@users.noreply.github.com> Date: Mon, 22 Jun 2026 13:13:25 -0400 Subject: [PATCH 35/39] Changed background colour of application (#1737) --- CHANGELOG.md | 2 ++ style/app.scss | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4099613db..18a01affb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ ### 🐛 Bug fixes +- Fixed CSS styling of background colour and let the application have full height + ### 🔧 Internal changes - Refactored the `Courses` table to `Course` with a database migration diff --git a/style/app.scss b/style/app.scss index 6a3cb4d5c..9918e1b69 100644 --- a/style/app.scss +++ b/style/app.scss @@ -65,6 +65,7 @@ html { } body { + background-color: #f0f8f5; color: #222; font-family: "Trebuchet MS", Arial, sans-serif; font-size: 17pt; @@ -511,7 +512,7 @@ ol { #container { background: #f0f5f8; - height: calc(100% - 50px); + height: 100%; position: relative; width: 100%; } From 4fbfb9d24b3b77e67b35d5047fc9faaeffe962c5 Mon Sep 17 00:00:00 2001 From: Jason De Lanerolle Date: Tue, 23 Jun 2026 11:40:04 -0400 Subject: [PATCH 36/39] resolve buildTimes --- app/Models/Time.hs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/app/Models/Time.hs b/app/Models/Time.hs index 9be774f5e..16a8a1b8d 100644 --- a/app/Models/Time.hs +++ b/app/Models/Time.hs @@ -8,19 +8,18 @@ import Models.Building (getBuilding) -- | Convert a Times record into a Time by resolving room codes to Buildings buildTime :: Times -> SqlPersistM Time buildTime t = do - room1 <- getBuilding (timesFirstRoom t) - room2 <- getBuilding (timesSecondRoom t) - return $ Time (timesWeekDay t) + location <- getBuilding (timesLocation t) + return $ Time (timesSession t) + (timesWeekDay t) (timesStartHour t) (timesEndHour t) - room1 - room2 + location buildTimes :: MeetingId -> Time' -> Times buildTimes meetingKey t = - Times (weekDay' t) + Times (timeSession' t) + (weekDay' t) (startHour' t) (endHour' t) meetingKey - (firstLocation' t) - (secondLocation' t) + (timeLocation' t) From d06db0862991f5719036d3bdcb806784733b6e6a Mon Sep 17 00:00:00 2001 From: Jason De Lanerolle Date: Wed, 24 Jun 2026 02:13:57 -0400 Subject: [PATCH 37/39] resolve TablesTests --- app/Database/Tables.hs | 2 +- backend-test/Database/TablesTests.hs | 16 +++++++--------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/app/Database/Tables.hs b/app/Database/Tables.hs index 57a6600ab..365b400db 100644 --- a/app/Database/Tables.hs +++ b/app/Database/Tables.hs @@ -166,7 +166,7 @@ data Time' = startHour' :: Double, endHour' :: Double, timeLocation' :: Maybe T.Text - } deriving (Show, Generic) + } deriving (Show, Eq, Generic) data Time = Time { timeSession :: Maybe T.Text, diff --git a/backend-test/Database/TablesTests.hs b/backend-test/Database/TablesTests.hs index bac1db7c0..9f6dcc9c9 100644 --- a/backend-test/Database/TablesTests.hs +++ b/backend-test/Database/TablesTests.hs @@ -45,15 +45,13 @@ runMeetingFromJSONTests = map runMeetingFromJSONTest meetingFromJSONTestCases time'FromJSONTestCases :: [(String, T.Text, Maybe Time')] time'FromJSONTestCases = [ ("Empty JSON string, Nothing returned", "", Nothing) - , ("Valid JSON string", "{ \"start\": { \"day\": 1, \"millisofday\": 36000000 }, \"end\": { \"millisofday\": 39600000 }, \"building\": { \"buildingCode\": \"BA\", \"buildingRoomNumber\": \"1130\" }, \"assignedRoom2\": \"MP102\" }", Just (Time' {weekDay' = 0.0, startHour' = 10.0, endHour' = 11.0, firstLocation' = Just "BA1130", secondLocation' = Just "MP102"})) - , ("Valid JSON string with no assignedRoom2", "{ \"start\": { \"day\": 2, \"millisofday\": 39600000 }, \"end\": { \"millisofday\": 43200000 }, \"building\": { \"buildingCode\": \"MP\", \"buildingRoomNumber\": \"203\" } }", Just (Time' {weekDay' = 1.0, startHour' = 11.0, endHour' = 12.0, firstLocation' = Just "MP203", secondLocation' = Nothing})) - , ("Valid JSON string with no day, default time values returned", "{ \"start\": { \"millisofday\": 43200000 }, \"end\": { \"millisofday\": 50400000 }, \"building\": { \"buildingCode\": \"MY\", \"buildingRoomNumber\": \"150\" } }", Just (Time' {weekDay' = 5.0, startHour' = 25.0, endHour' = 25.0, firstLocation' = Just "MY150", secondLocation' = Nothing})) - , ("Valid JSON string with no start millisofday, default time values returned", "{ \"start\": { \"day\": 3 }, \"end\": { \"millisofday\": 50400000 }, \"building\": { \"buildingCode\": \"MY\", \"buildingRoomNumber\": \"150\" } }", Just (Time' {weekDay' = 5.0, startHour' = 25.0, endHour' = 25.0, firstLocation' = Just "MY150", secondLocation' = Nothing})) - , ("Valid JSON string with no end millisofday, default time values returned", "{ \"start\": { \"day\": 3, \"millisofday\": 43200000 }, \"end\": { }, \"building\": { \"buildingCode\": \"MY\", \"buildingRoomNumber\": \"150\" } }", Just (Time' {weekDay' = 5.0, startHour' = 25.0, endHour' = 25.0, firstLocation' = Just "MY150", secondLocation' = Nothing})) - , ("Invalid JSON string with no start value, Nothing returned", "{ \"end\": { \"millisofday\": 54000000 }, \"building\": { \"buildingCode\": \"MP\", \"buildingRoomNumber\": \"202\" } }", Nothing) - , ("Invalid JSON string with no end value, Nothing returned", "{ \"start\": { \"day\": 4, \"millisofday\": 50400000 }, \"building\": { \"buildingCode\": \"MP\", \"buildingRoomNumber\": \"202\" } }", Nothing) - , ("Invalid JSON string with no buildingCode value, Nothing returned", "{ \"start\": { \"day\": 4, \"millisofday\": 50400000 }, \"end\": { \"millisofday\": 54000000 }, \"building\": { \"buildingRoomNumber\": \"202\" } }", Nothing) - , ("Invalid JSON string with no buildingRoomNumber value, Nothing returned", "{ \"start\": { \"day\": 4, \"millisofday\": 50400000 }, \"end\": { \"millisofday\": 54000000 }, \"building\": { \"buildingCode\": \"MP\" } }", Nothing) + , ("Valid JSON string", "{ \"start\": { \"day\": 1, \"millisofday\": 36000000 }, \"end\": { \"millisofday\": 39600000 }, \"building\": { \"buildingCode\": \"BA\", \"buildingRoomNumber\": \"1130\" }, \"sessionCode\": \"20269\" }", Just (Time' {timeSession' = Just "20269", weekDay' = 0.0, startHour' = 10.0, endHour' = 11.0, timeLocation' = Just "BA"})) + , ("Valid JSON string with no day, default time values returned", "{ \"start\": { \"millisofday\": 43200000 }, \"end\": { \"millisofday\": 50400000 }, \"building\": { \"buildingCode\": \"MY\", \"buildingRoomNumber\": \"150\" }, \"sessionCode\": \"20271\" }", Just (Time' {timeSession' = Just "20271", weekDay' = 5.0, startHour' = 25.0, endHour' = 25.0, timeLocation' = Just "MY"})) + , ("Valid JSON string with no start millisofday, default time values returned", "{ \"start\": { \"day\": 3 }, \"end\": { \"millisofday\": 50400000 }, \"building\": { \"buildingCode\": \"MY\", \"buildingRoomNumber\": \"150\" }, \"sessionCode\": \"20271\" }", Just (Time' {timeSession' = Just "20271", weekDay' = 5.0, startHour' = 25.0, endHour' = 25.0, timeLocation' = Just "MY"})) + , ("Valid JSON string with no end millisofday, default time values returned", "{ \"start\": { \"day\": 3, \"millisofday\": 43200000 }, \"end\": { }, \"building\": { \"buildingCode\": \"MY\", \"buildingRoomNumber\": \"150\" }, \"sessionCode\": \"20271\" }", Just (Time' {timeSession' = Just "20271", weekDay' = 5.0, startHour' = 25.0, endHour' = 25.0, timeLocation' = Just "MY"})) + , ("Invalid JSON string with no start value, Nothing returned", "{ \"end\": { \"millisofday\": 54000000 }, \"building\": { \"buildingCode\": \"MP\", \"buildingRoomNumber\": \"202\" }, \"sessionCode\": \"20269\" }", Nothing) + , ("Invalid JSON string with no end value, Nothing returned", "{ \"start\": { \"day\": 4, \"millisofday\": 50400000 }, \"building\": { \"buildingCode\": \"MP\", \"buildingRoomNumber\": \"202\" }, \"sessionCode\": \"20269\" }", Nothing) + , ("Invalid JSON string with no buildingCode value, Nothing returned", "{ \"start\": { \"day\": 4, \"millisofday\": 50400000 }, \"end\": { \"millisofday\": 54000000 }, \"building\": { \"buildingRoomNumber\": \"202\" }, \"sessionCode\": \"20269\" }", Nothing) ] -- | Run a test case (label, input JSON string, expected output) on the FromJSON instance of Time'. From 65528f632d2860bd0e6e14039ed3927fda12d0cc Mon Sep 17 00:00:00 2001 From: Jason De Lanerolle Date: Wed, 24 Jun 2026 02:47:49 -0400 Subject: [PATCH 38/39] fix duplicate changelog lines --- CHANGELOG.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b3ece7b5c..162eb610a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -56,10 +56,6 @@ - Refactor `Times` database schema to encompass only a single session of a course - Change `Time` and `Time'` datatypes to match the database schema, and resolve resulting compilation and type errors -#### y-course-refactor mini changelog (to replace): -- Refactor `Times` database schema to encompass only a single session of a course -- Change `Time` and `Time'` datatypes to match the database schema, and resolve resulting compilation and type errors - ## [0.7.2] - 2025-12-10 ### ✨ New features/enhancements From 881bfecfd2c110d56f89292e160e8d488e5a8dad Mon Sep 17 00:00:00 2001 From: Jason De Lanerolle Date: Wed, 24 Jun 2026 03:49:09 -0400 Subject: [PATCH 39/39] add Y session display logic (no tests yet) --- js/components/common/react_modal.js.jsx | 135 +++++++++++++++++++++--- 1 file changed, 120 insertions(+), 15 deletions(-) diff --git a/js/components/common/react_modal.js.jsx b/js/components/common/react_modal.js.jsx index 996e7fac8..4928eb389 100644 --- a/js/components/common/react_modal.js.jsx +++ b/js/components/common/react_modal.js.jsx @@ -133,8 +133,12 @@ class CourseModal extends React.Component { } } - /* Generate the data needed for each row of the timetable based on course meeting times for - * each session F, S, Y. + /** + * Generate the data needed for the course modal table based on the meeting times corresponding + * to a course in a given session. + * @param allMeetingTimes An array of MeetTime' objects corresponding to a particular course. + * @param session The session (F, S, Y) to query. + * @returns A map containing the table data that will appear in the course modal. */ getTable(allMeetingTimes, session) { const sessions = allMeetingTimes.filter(lec => lec.meetData.session === session) @@ -144,6 +148,7 @@ class CourseModal extends React.Component { return sortedSessions.map(lecture => { const occurrences = { times: [], locations: [] } + const yearOccurrences = {fallTimes: [], fallLocations: [], winterTimes: [], winterLocations: []} const sortedTimeData = lecture.timeData.sort((occ1, occ2) => occ1.weekDay > occ2.weekDay ? 1 : -1 ) @@ -152,14 +157,42 @@ class CourseModal extends React.Component { if (occurrence.timeLocation !== null && occurrence.timeLocation !== undefined) { location = occurrence.timeLocation.buildingCode } - occurrences.locations.push(location) - occurrences.times.push( - DAY_TO_INT[occurrence.weekDay] + - " " + - occurrence.startHour + - " - " + - occurrence.endHour - ) + + // Time and location formatting for Y session courses + if (session === "Y") { + if (occurrence.timeSession.endsWith("9")) { + yearOccurrences.fallLocations.push(location) + yearOccurrences.fallTimes.push( + DAY_TO_INT[occurrence.weekDay].substring(0, 3) + + " " + + occurrence.startHour + + " - " + + occurrence.endHour + ) + } + else { + yearOccurrences.winterLocations.push(location) + yearOccurrences.winterTimes.push( + DAY_TO_INT[occurrence.weekDay].substring(0, 3) + + " " + + occurrence.startHour + + " - " + + occurrence.endHour + ) + } + } + + // Time and location formatting for F/S courses + else { + occurrences.locations.push(location) + occurrences.times.push( + DAY_TO_INT[occurrence.weekDay] + + " " + + occurrence.startHour + + " - " + + occurrence.endHour + ) + } }) const rowData = { activity: lecture.meetData.section, @@ -169,10 +202,14 @@ class CourseModal extends React.Component { lecture.meetData.enrol + " of " + lecture.meetData.cap + - " available", + (session === "Y" ? "" : " available"), // Account for shortened column width for Y courses waitList: lecture.meetData.wait + " students", time: occurrences.times, location: occurrences.locations, + fallTime: yearOccurrences.fallTimes, + fallLocation: yearOccurrences.fallLocations, + winterTime: yearOccurrences.winterTimes, + winterLocation: yearOccurrences.winterLocations } return rowData @@ -269,10 +306,12 @@ class Description extends React.Component { col.data.time.join("\n"), width: 180, autoHeight: true, + hide: session === "Y", }, { field: "location", @@ -296,6 +336,71 @@ class Description extends React.Component { valueFormatter: col => col.data.location.join("\n"), width: 128, autoHeight: true, + hide: session === "Y" + }, + + /* Y session occurrence columns */ + { + field: "fallTime", + cellStyle: { + whiteSpace: "pre", + lineHeight: "1.8", + paddingTop: "7px", + paddingBottom: "6px", + }, + valueFormatter: col => col.data.fallTime.join("\n"), + width: 115, + autoHeaderHeight: false, + autoHeight: true, + wrapHeaderText: true, + autoHeaderHeight: true, + hide: session !== "Y", + }, + { + field: "fallLocation", + cellStyle: { + whiteSpace: "pre", + lineHeight: "1.8", + paddingTop: "7px", + paddingBottom: "6px", + }, + valueFormatter: col => col.data.fallLocation.join("\n"), + width: 93, + autoHeaderHeight: false, + autoHeight: true, + wrapHeaderText: true, + autoHeaderHeight: true, + hide: session !== "Y", + }, + { + field: "winterTime", + cellStyle: { + whiteSpace: "pre", + lineHeight: "1.8", + paddingTop: "7px", + paddingBottom: "6px", + }, + valueFormatter: col => col.data.winterTime.join("\n"), + width: 115, + autoHeight: true, + wrapHeaderText: true, + autoHeaderHeight: true, + hide: session !== "Y", + }, + { + field: "winterLocation", + cellStyle: { + whiteSpace: "pre", + lineHeight: "1.8", + paddingTop: "7px", + paddingBottom: "6px", + }, + valueFormatter: col => col.data.winterLocation.join("\n"), + width: 93, + autoHeight: true, + wrapHeaderText: true, + autoHeaderHeight: true, + hide: session !== "Y", }, ]} domLayout="autoHeight"