Compare commits

...
996 Commits
Author SHA1 Message Date
Valtteri Kantanen c115323b93 [Faculties] Fix background colors in 'Students of the faculty' table 2024-07-26 17:22:12 +03:00
Valtteri Kantanen 503e5a9d43 [Backend] Refresh faculties only after all programmes have been refreshed 2024-07-26 16:26:38 +03:00
Valtteri Kantanen 0a40444ece [Backend] Fix migrations folder location in staging 2024-07-26 15:06:33 +03:00
Valtteri Kantanen c330f0653a [Class statistics] Fix tests 2024-07-26 14:44:38 +03:00
Valtteri Kantanen 6ad8d36060 [Faculties] Add a null check for programme year stats 2024-07-26 14:34:52 +03:00
Valtteri Kantanen c9aabecb5a [Faculties] Reflect recent backend code changes in the frontend 2024-07-26 13:23:19 +03:00
Valtteri Kantanen 116b4d775f Remove lines from pre-commit hook that will be deprecated in Husky v10 2024-07-26 13:19:24 +03:00
Valtteri Kantanen 27093f56f2 [Faculties] Update tooltip texts 2024-07-26 13:12:59 +03:00
Valtteri Kantanen 45177d6020 [Faculties] Big refactor: Students of the faculty by starting year 2024-07-26 13:12:00 +03:00
Riku RauhalaandGitHub cecb3ca757 Merge pull request #4529 from UniversityOfHelsinkiCS/renovate/all-minor-patch
Update all non-major dependencies
2024-07-26 11:16:08 +03:00
Riku Rauhala 4380cc5fdc [Prettier] Remove ts parser 2024-07-26 11:12:21 +03:00
renovate[bot]andGitHub 43f83c9392 Update all non-major dependencies 2024-07-26 08:05:25 +00:00
Riku Rauhala 15e2801c68 Upgrade prettier and eslint-plugin-prettier and fix issues 2024-07-26 10:55:21 +03:00
Riku RauhalaandGitHub 285cc76763 Merge pull request #4541 from UniversityOfHelsinkiCS/renovate/use-context-selector-2.x
Update dependency use-context-selector to v2
2024-07-26 10:08:01 +03:00
Riku Rauhala adcaacbb65 [Cypress] Increase the number of retries for flaky filter tests 2024-07-26 10:07:43 +03:00
renovate[bot]andGitHub 7daf0b820e Update dependency use-context-selector to v2 2024-07-26 06:59:29 +00:00
Riku Rauhala f1be7ebaff [Actions] Remove tsMerge branch from staging.yaml 2024-07-26 09:57:11 +03:00
Riku Rauhala 8c7aa9c3ed [Scripts] Update instrument.sh 2024-07-26 09:50:14 +03:00
Riku Rauhala 255626b4b9 Update docker-compose.test.yml 2024-07-26 09:48:05 +03:00
Riku Rauhala 97ef63c655 Add more specific Cypress commands for testing 2024-07-26 09:47:33 +03:00
Riku Rauhala 23c815305d [Backend] Type customOpenUniSearch route requests 2024-07-26 08:33:30 +03:00
Riku Rauhala fea2148d27 [Backend] Improve request/response types for routes 2024-07-25 21:44:54 +03:00
Riku Rauhala 0cf89f5d90 [Backend] Type routes/usersFd 2024-07-25 21:33:06 +03:00
Riku Rauhala 4317f22c64 [Backend] Type routes/users 2024-07-25 21:04:58 +03:00
Riku Rauhala 2762f843ab [Backend] Add type IamAccess 2024-07-25 21:02:40 +03:00
Riku Rauhala 4c8a0efbb7 [Backend] Type util/jami 2024-07-25 21:02:11 +03:00
Riku Rauhala c0d36dcd5f [Backend] Rename currentUserMiddleware 2024-07-25 14:50:29 +03:00
Riku Rauhala f02b537a05 [Backend] type headers middleware 2024-07-25 14:49:42 +03:00
Riku Rauhala 01c0870828 [Backend] Type errorHandler middleware 2024-07-25 14:28:56 +03:00
Riku Rauhala 6634d2c6a1 [Backend] Type middleware/accessLogger 2024-07-25 14:18:31 +03:00
Riku Rauhala 236c308725 [Backend] Install @types/morgan as a dev dependency 2024-07-25 14:01:05 +03:00
Riku Rauhala a51efab717 [Backend] Mark curriculumVersion as optional in model ProgressCriteria 2024-07-25 13:14:10 +03:00
Riku Rauhala decf5781dd [Backend] Type middleware/auth 2024-07-25 13:03:16 +03:00
Valtteri Kantanen 8fc14d15f4 [Backend] Improve types 2024-07-25 10:18:33 +03:00
Valtteri Kantanen 8056a3146d [Study programme overview] Improve layout on Programme courses tab 2024-07-25 10:14:56 +03:00
Valtteri Kantanen 7d11edfefa [Study programme overview] Add a separate info text to Programme courses tab
This is the same text as in CreditsProducedByTheStudyprogramme before changing the categories on Basic information tab
2024-07-25 10:13:47 +03:00
Riku RauhalaandGitHub 996af84673 Merge pull request #4578 from UniversityOfHelsinkiCS/ts-test-branch
Delete foreign key from studyright (actual_studyrightid)
2024-07-25 09:30:13 +03:00
Riku Rauhala 7e2638f492 [Backend] Type services/studyGuidanceGroups 2024-07-25 09:29:33 +03:00
Valtteri KantanenandGitHub 8983fb4762 Merge pull request #4584 from UniversityOfHelsinkiCS/backend-multi-stage-build
[Backend] Multi-stage build to make final Docker image smaller
2024-07-24 17:39:52 +03:00
Valtteri Kantanen 92005e42a2 [Backend] Fix migration folder path 2024-07-24 17:31:29 +03:00
Valtteri Kantanen 698aaf8664 [Backend] Try a multi-stage build to make final Docker image smaller 2024-07-24 17:16:31 +03:00
Valtteri Kantanen 9fff78edae Delete deprecated rapodiff code 2024-07-24 15:47:23 +03:00
Riku Rauhala af797179ad [Backend] Use more detailed request types 2024-07-24 15:01:44 +03:00
Riku Rauhala 9bbc8b3caa [Course exclusions] Improve typing 2024-07-24 14:54:12 +03:00
Valtteri KantanenandGitHub 0f643a5b83 Merge pull request #4582 from UniversityOfHelsinkiCS/OOD-35
[FrontPage][NavigationBar] Added conditional renders based on serviceProvider to FrontPage and NavigationBar components
2024-07-24 14:12:21 +03:00
Valtteri KantanenandGitHub 087242d34a Merge pull request #4583 from UniversityOfHelsinkiCS/all-bigints-to-strings
[Backend] Change representation of bigint columns to strings in TypeScript
2024-07-24 14:04:26 +03:00
Valtteri KantanenandGitHub 8592ac88c0 Merge pull request #4581 from UniversityOfHelsinkiCS/OOD-28
[Updater] Fix how customCourseUnitAttainments are created as courses
2024-07-24 14:03:24 +03:00
Valtteri Kantanen 8214556cff [Backend] Change representation of bigint columns to strings in TypeScript 2024-07-24 13:55:04 +03:00
Riku Rauhala e02d56a3b4 [Frontend] Bump unfuck-spa-shibboleth-session to 4.1.0 2024-07-24 11:59:38 +03:00
Riku Rauhala 03b5421f97 [Backend] Fix tests 2024-07-24 11:40:36 +03:00
Riku Rauhala e3a7ffe827 [Backend] Add missing parameter types to openUni/format 2024-07-24 11:23:01 +03:00
Riku Rauhala e415adbc61 [Backend] Type customOpenUniSearch 2024-07-24 11:10:37 +03:00
Riku Rauhala 9082e36677 [Backend] Improve currentUserMiddleware typing 2024-07-24 11:03:53 +03:00
Riku Rauhala 36c0a12ed6 [Backend] Add logoutUrl to OodikoneRequest 2024-07-24 10:27:37 +03:00
Riku Rauhala 5e564b7bc1 [Backend] Type currentUserMiddleware 2024-07-24 10:26:38 +03:00
Matti Räsänen 0c0207f6fb [Updater] Added isModule to exports in mapper and took in to use in addCourseUnitToCustomCourseUnitAttainments. Removed const parsedCourseCode and using attainment id in courseProviderMapper 2024-07-24 09:12:18 +03:00
Riku Rauhala f52616780b [Backend] Type completedCoursesSearch 2024-07-23 20:24:49 +03:00
Riku Rauhala d503560c5d [Backend] Create enum EnrollmentState 2024-07-23 17:58:33 +03:00
Riku Rauhala f46ffbf561 [Backend] Type routes/studyGuidanceGroups 2024-07-23 14:46:11 +03:00
Riku Rauhala 59b74ecc37 [Backend] Type routes/studyProgramme 2024-07-23 14:23:45 +03:00
Riku Rauhala 9ae2d84c6b [Backend] Extract common functionality to eliminate copy-paste 2024-07-23 13:50:35 +03:00
Tereshchenko Aleksandr 0b74234421 renovate: Label security PRs with 'security' label 2024-07-23 12:57:09 +03:00
Riku Rauhala 9723fd1944 [Backend] Type services/studyProgrammeCriteria 2024-07-23 11:58:56 +03:00
Riku Rauhala 2ffb798830 [Documentation] Simplify database relation diagrams 2024-07-23 10:29:41 +03:00
Matti Räsänen a805dbba8a [NavigationBar] Added serviceProvider check to few routes 2024-07-23 08:59:26 +03:00
Matti Räsänen 6fc4a8f542 [NavigationBar] Added conditional render when serviceProvider is Toska to special populations open uni and language center views 2024-07-23 08:58:48 +03:00
Matti Räsänen 95804bf301 [Frontpage] Edited to show Feedback section only if serviceProvider is Toska 2024-07-23 08:40:16 +03:00
Riku Rauhala f65621f028 [Backend] Type routes/studyProgrammeCriteria 2024-07-22 19:13:56 +03:00
Riku Rauhala 7aa3f3db6b [Backend] Type routes/studyProgrammePins 2024-07-22 19:11:16 +03:00
Riku Rauhala a25a16402c [Backend] Type routes/customPopulationSearch 2024-07-22 18:59:23 +03:00
Riku Rauhala 4c68b0df38 [Backend] Type routes/semesters 2024-07-22 18:42:34 +03:00
Riku Rauhala ad3fa1c5d7 [Backend] Type routes/programmeModules 2024-07-22 18:02:37 +03:00
Riku Rauhala 40f7abc8a0 [Backend] Type routes/languageCenterData 2024-07-22 17:54:24 +03:00
Riku Rauhala 407c092464 [Backend] type routes/courseExclusions 2024-07-22 17:49:33 +03:00
Riku Rauhala f2d9f1f4b0 [Backend] Add missing auto increment to model ExcludedCourse 2024-07-22 17:22:07 +03:00
Riku Rauhala 050e010358 [Backend] Type routes/closeToGraduation 2024-07-22 15:45:24 +03:00
Riku Rauhala fb918001f5 [Backend] Type routes/providers 2024-07-22 15:25:38 +03:00
Riku Rauhala 9903604c0b [Backend] Acually type routes/feedback 2024-07-22 15:18:53 +03:00
Valtteri Kantanen 6f8b6133e5 Revert "[Backend] Type routes/feedback"
This reverts commit d8dcf1608d.
2024-07-22 15:10:54 +03:00
ShootingStar91 1118d2b2da Remove deprecated route 2024-07-22 15:08:42 +03:00
Riku Rauhala d8dcf1608d [Backend] Type routes/feedback 2024-07-22 15:01:21 +03:00
Valtteri Kantanen 592832eb95 [Study programme overview] Extract function for checking if student has transferred from or to programme 2024-07-22 14:51:18 +03:00
Riku Rauhala dba5045982 Revert [Backend] Enable path aliases 2024-07-22 14:27:03 +03:00
Riku Rauhala 2513986361 [Backend] Enable path aliases 2024-07-22 14:17:21 +03:00
Riku Rauhala e7dee7f139 [Backend] Type routes/changelog 2024-07-22 14:00:53 +03:00
Matti Räsänen 548f3fc622 Merge branch 'master' into OOD-28 2024-07-22 13:50:32 +03:00
Riku Rauhala fdcc7648c5 [Backend] Remove logoutUrl missing error 2024-07-22 13:48:03 +03:00
Riku Rauhala b3ddbf669a [Backend] Type routes/login 2024-07-22 13:25:43 +03:00
Riku Rauhala ca00efffd4 [Backend] Install @types/express as a dev dependency 2024-07-22 13:25:43 +03:00
Valtteri Kantanen b73850c8c6 [Study programme overview] Fix type error 2024-07-22 13:14:01 +03:00
Valtteri Kantanen db86b1a8d3 [Study programme overview] Use new models to calculate thesis writer stats 2024-07-22 12:49:47 +03:00
Matti Räsänen b43e99afbf [Course statistics] Changed toCourseRow key to use course.id instead of course.code because there could be multiple courses with same code 2024-07-22 10:32:24 +03:00
Valtteri Kantanen 6c27c11356 [Study programme overview] Exclude students who have transferred away from programme when 'includeAllSpecials' is false 2024-07-22 10:29:24 +03:00
Valtteri Kantanen 5e4f5b5e7a [Study programme overview] Fetch students only once when calculating study track stats 2024-07-22 10:29:24 +03:00
Valtteri Kantanen e9b7c677f8 [Evaluation overview] Align graduation times toggles horizontally 2024-07-22 10:29:24 +03:00
Valtteri Kantanen 7fa8ec5176 [Study programme overview] Update texts in infoboxes 2024-07-22 10:29:24 +03:00
Valtteri Kantanen 027899234f [Evaluation overview] Don't try to render objects 2024-07-22 10:29:24 +03:00
Valtteri Kantanen 5e223eb749 [Backend] Upgrade typescript from 5.4.5 to 5.5.3 2024-07-22 10:29:24 +03:00
Valtteri Kantanen cf5049db05 Remove strictPropertyInitialization: false from tsconfig.json 2024-07-22 10:29:24 +03:00
Valtteri Kantanen d20db4feb4 [Backend] Fix types 2024-07-22 10:29:24 +03:00
Valtteri Kantanen d214fe0282 [Backend] Add InferAttributes to all models and definite assignment assertions to all their properties 2024-07-22 10:29:24 +03:00
Riku Rauhala 492ad09e36 [Documentation] Document kone-db 2024-07-19 21:31:45 +03:00
Riku Rauhala f62cb9718c Create resources.md 2024-07-19 21:26:02 +03:00
Riku Rauhala a6ac9493d6 [Documentation] Document user-db 2024-07-19 21:26:02 +03:00
Valtteri Kantanen 93f1c3dc99 [Study programme overview] Remove pop-up from 'Other countries' table cell if there are no students from other countries 2024-07-19 17:30:14 +03:00
Valtteri Kantanen 853c4ceba5 [Study programme overview] Sort graduation stats by starting year in descending order 2024-07-19 17:30:14 +03:00
Valtteri Kantanen d485fc604d [Study programme overview] Update infobox texts to reflect recent changes 2024-07-19 17:30:14 +03:00
Valtteri Kantanen 68af9ab38c [Frontend] Update dependency unfuck-spa-shibboleth-session 2024-07-19 17:30:14 +03:00
Valtteri Kantanen 899d5e4e43 [Backend] Update tsx, remove nodemon and ts-node from dependencies 2024-07-19 17:30:14 +03:00
Riku Rauhala 4aadf329ea [Backend] Type organization service 2024-07-19 17:26:26 +03:00
Riku Rauhala 23ebb69778 [Backend] Type provider service 2024-07-19 16:30:02 +03:00
EssKayz 750fb03e9c [FD-Compose] Replicate updater-worker 2024-07-19 16:02:28 +03:00
EssKayz 49932ec15e [Updater] : Fix how customCourseUnitAttainments are created as courses 2024-07-19 16:01:10 +03:00
EssKayz d7b0e02174 [Backend] Fix courseIdToShare exploding when providers is undefined 2024-07-19 16:01:07 +03:00
Riku Rauhala 855ca8e134 [Backend] Type mailService 2024-07-19 13:29:04 +03:00
Riku RauhalaandGitHub 9b21a4a1d4 Merge pull request #4579 from UniversityOfHelsinkiCS/fd-get-user-fix
[Backend] Renamed programmeRights to detailedProgrammeRights in fdGetUser
2024-07-19 13:22:57 +03:00
Valtteri Kantanen c083803858 [Backend] Fix error logging 2024-07-19 13:22:38 +03:00
Matti Räsänen 62735ab481 [Backend] Renamed programmeRights to detailedProgrammeRights in fdGetUser 2024-07-19 13:14:07 +03:00
Valtteri Kantanen cd252469e3 [Study programme overview] Add more specific types 2024-07-19 11:59:24 +03:00
Riku Rauhala 4ff5e42752 [Faculties] Remove refences to csv
Downloads are in xlsx format, not csv
2024-07-19 10:45:03 +03:00
Riku Rauhala d755aaab92 [Frontend] Refactor to remove identical code 2024-07-19 10:41:55 +03:00
Riku Rauhala b98b03b4a0 [Frontend] Fix a typo 2024-07-19 08:57:23 +03:00
Riku RauhalaandGitHub 6d7dfad89a Merge pull request #4577 from UniversityOfHelsinkiCS/type-user-service
Type user service
2024-07-18 20:52:34 +03:00
Riku Rauhala 6070486745 [Backend] Fix TypeScript issues 2024-07-18 20:35:55 +03:00
Riku RauhalaandGitHub f5ee0211a4 Merge branch 'master' into type-user-service 2024-07-18 20:10:30 +03:00
Riku Rauhala 49e1b3e99d [Backend] Fix fetching user 2024-07-18 20:03:57 +03:00
Valtteri Kantanen d5256f9b39 [Backend] Remove strictNullChecks: false from tsconfig.json 2024-07-18 17:39:27 +03:00
Valtteri Kantanen 3bdf76ed03 [Backend] Fix createLocaleComparator 2024-07-18 17:38:01 +03:00
Valtteri Kantanen cc692f34c3 [Backend] Add null checks to students.ts and add a util function keysOf 2024-07-18 17:37:30 +03:00
Valtteri Kantanen 98a56eead4 [Study programme overview] Fix tests 2024-07-18 15:40:04 +03:00
Riku Rauhala b823d0f23a [Backend] Extract type DetailedProgrammeRights 2024-07-18 15:39:47 +03:00
ShootingStar91andRiku Rauhala a3648898e6 Add SIS-models foreign keys 2024-07-18 15:39:47 +03:00
ShootingStar91andRiku Rauhala 0b64a9a11f Add faculty code as foreign key to sisstudyright 2024-07-18 15:39:47 +03:00
Valtteri KantanenandRiku Rauhala 4bb61d0784 [Study programme overview] Use new models in average graduation times calculations 2024-07-18 15:39:47 +03:00
ShootingStar91 b879034931 Delete foreign key from studyright (actual_studyrightid) 2024-07-18 15:36:12 +03:00
Arttu KangasandGitHub 71bc53d787 Merge pull request #4576 from UniversityOfHelsinkiCS/ts-test-branch
Add faculty code as foreign key to sisstudyright
2024-07-18 15:34:44 +03:00
Valtteri Kantanen 005107882c [Study programme overview] Use new models in average graduation times calculations 2024-07-18 15:31:21 +03:00
Riku Rauhala 367376065e [Backend] Update createLocaleComparator 2024-07-18 15:30:29 +03:00
Riku Rauhala 45b72cef56 [Backend] Improve userService typing 2024-07-18 15:30:29 +03:00
Riku Rauhala 60ff7a210d [Backend] Type and refactor userService 2024-07-18 15:30:29 +03:00
ShootingStar91 0c7de151ba Add SIS-models foreign keys 2024-07-18 15:27:37 +03:00
ShootingStar91 32d7ef4534 Add faculty code as foreign key to sisstudyright 2024-07-18 15:10:50 +03:00
ShootingStar91 5bb39442b0 [Students] Fix student name disappearing 2024-07-18 15:01:46 +03:00
ShootingStar91 a8afade3b2 Type services/students.ts 2024-07-18 14:38:30 +03:00
Riku RauhalaandGitHub fb3acf1f34 Merge pull request #4575 from UniversityOfHelsinkiCS/OOD-34-fixes
[Updater] Added null check fallback to abbreviation in initGradeScaleIdToGradeIdsToGrades
2024-07-18 14:01:31 +03:00
Matti Räsänen 0a7db609d2 [Updater] Added null check fallback to abbreviation in initGradeScaleIdToGradeIdsToGrades 2024-07-18 13:56:22 +03:00
ShootingStar91 886f84d6df Update SortableTable docs & add link to root README 2024-07-18 13:44:53 +03:00
ShootingStar91 5e22c82ca0 Make SortableTable doc into markdown table 2024-07-18 13:40:14 +03:00
Riku RauhalaandGitHub 820c1d7a2e Merge pull request #4574 from UniversityOfHelsinkiCS/OOD-38
[Backend] Moved organisation related stuff to environment/organizationConfig.json file. Added conditional check to routes for users end point
2024-07-18 12:52:40 +03:00
Matti Räsänen 6a68350203 [Backend] Moved facultyCodes, magicFacultyCode, ignoredFacultyCodes to environment/organizationConfig.json file. Added resolveJsonModule to tsconfig 2024-07-18 12:05:47 +03:00
Matti Räsänen a71c6d51f1 [Backend] Moved facultyCodes, magicFacultyCode, ignoredFacultyCodes to environment/organizationConfig.json file. Edited usersFd route to have only fd related routes and added conditional check to routes to include this routes only when SERVICE_PROVIDER Fd. 2024-07-18 12:04:37 +03:00
Valtteri Kantanen bf93df66fe [Updater] Fix log message formatting in production 2024-07-18 11:47:45 +03:00
Valtteri Kantanen de62e7f528 [Backend] Improve and fix types 2024-07-18 10:42:45 +03:00
Riku Rauhala 854c8e5228 [Backend] Create type Language 2024-07-18 09:13:02 +03:00
Riku Rauhala 150d06e27b [Backend] Move Oodikone roles to config
Also form the Role type based on the list stored in config
2024-07-17 21:29:38 +03:00
Valtteri Kantanen 28ea80b1d0 Try uploading backend source maps into Sentry 2024-07-17 19:14:27 +03:00
Valtteri Kantanen 95a97f2c37 [Backend] Fix some types 2024-07-17 19:04:11 +03:00
Valtteri Kantanen ba35393c7d [Backend] Update TypeScript settings
Target was updated from ES6 to ES2021 as backend runs on Node 20. Also lib is specified to be ES2023 so that we are able to use methods like `Array.at()` or `Array.toSorted()` with types. Also strict is changed to true but all the individual rules that currently cause problems have been disabled.
2024-07-17 18:55:55 +03:00
Riku Rauhala c5c5889791 [Backend] Remove duplicated code 2024-07-17 18:31:16 +03:00
Riku Rauhala 75968b0b16 [Backend] Type courseFinders 2024-07-17 18:27:15 +03:00
Riku Rauhala 30b9c33f21 [Backend] Move conf-backend to config directory 2024-07-17 17:27:00 +03:00
Valtteri Kantanen fa9324431d [Study programme overview] Fix tests 2024-07-17 16:28:36 +03:00
Valtteri Kantanen e2dc26d4af [Backend] Change sentry.ts back to sentry.js 2024-07-17 15:51:43 +03:00
Valtteri Kantanen 12a405ed08 [Study programme overview] Update headers on study track stats table 2024-07-17 15:33:03 +03:00
Valtteri Kantanen dea2db5497 [Backend] Delete unused exports 2024-07-17 15:31:52 +03:00
Valtteri Kantanen 925e6646f0 [Backend] Add better types 2024-07-17 15:30:39 +03:00
Valtteri Kantanen 09889ba66f [Study programme overview] Use new models in study track stats 2024-07-17 15:25:07 +03:00
Riku Rauhala 1332a0ad29 [Backend] Type more utils 2024-07-17 15:21:35 +03:00
Riku Rauhala 281e142d5c [Backend] Type semester utils 2024-07-17 15:12:54 +03:00
Riku Rauhala ddac6ea36c [Backend] Improve util typing 2024-07-17 13:42:04 +03:00
Riku Rauhala 2aedf1efe8 [Backend] Type utils and remove duplicate code 2024-07-17 12:05:10 +03:00
Riku Rauhala 9edca0fc50 [Backend] Create a more accurate type for Role 2024-07-17 11:54:29 +03:00
Riku Rauhala 6bad2bc5dd [Backend] Revert changes to models 2024-07-16 21:57:50 +03:00
Riku Rauhala a1365406ae [Backend] Use explicit foreign key definitions for studyrights and organization 2024-07-16 21:47:43 +03:00
Riku Rauhala 8a66030f3b [Backend] Revert changes to models 2024-07-16 21:16:08 +03:00
Riku Rauhala ae82cfb333 [Backend] Import types from an index file 2024-07-16 20:59:45 +03:00
Riku Rauhala 4f9b87b591 [Backend] Use the correct StudyTrack type in SISStudyRightElement 2024-07-16 20:47:48 +03:00
Riku Rauhala 508d9d0479 [Backend] Explicitly define foreign keys for SISStudyRight and SISStudyRightElement 2024-07-16 20:37:06 +03:00
Riku Rauhala 3f83d6caaa Revert "[Backend] Explicitly define foreign keys"
This reverts commit 1071d085c7.
2024-07-16 19:20:32 +03:00
Riku Rauhala 1071d085c7 [Backend] Explicitly define foreign keys 2024-07-16 18:29:10 +03:00
Valtteri Kantanen e92726c06a Fix ESLint errors 2024-07-16 16:47:40 +03:00
Valtteri Kantanen e4831c16d8 Add ESLint settings for TypeScript files 2024-07-16 16:07:33 +03:00
Valtteri Kantanen e231a2046f [Updater] Remove colors from logs in production 2024-07-16 15:18:18 +03:00
Valtteri Kantanen 4ea39bd13b [Close to graduation] Handle the rare situation where there are no semester enrollments related to the selected study right 2024-07-16 15:11:01 +03:00
Valtteri Kantanen 9ed0576989 [Backend] Add a better type for semester enrollments 2024-07-16 12:49:15 +03:00
Valtteri Kantanen c64ebfdf46 [Backend] Type semesters.ts 2024-07-16 12:36:33 +03:00
Valtteri Kantanen 6bd7eed960 [Close to graduation] Export function findStudentsCloseToGraduation to update data 2024-07-16 12:36:33 +03:00
Riku Rauhala 0f65cf014b [Backend] Type faculty.ts 2024-07-16 12:00:37 +03:00
Riku Rauhala 97b5879660 [Backend] Remove console.time 2024-07-16 11:08:45 +03:00
Riku Rauhala a75e333de8 [Backend] Move @types/umzug to dev dependencies 2024-07-16 09:55:00 +03:00
Riku RauhalaandGitHub a97e17affa Merge pull request #4573 from UniversityOfHelsinkiCS/fd-docker-compose-changes-to-volumes
[FD compose] Edited backend and frontend volumes. Added also REACT_APP_SERVICE_PROVIDER env variable to frontend.
2024-07-16 08:58:36 +03:00
Matti Räsänen ddc682850f [FD compose] Edited backend and frontend volumes. Added also REACT_APP_SERVICE_PROVIDER env variable to frontend. 2024-07-16 08:41:05 +03:00
Riku Rauhala f16ee68853 [Backend] Use ExtentCode in facultyHelpers 2024-07-16 08:31:04 +03:00
Riku Rauhala 07d43e9efd [Backend] Use ExtentCode in studyProgrammeGraduations 2024-07-16 08:28:15 +03:00
Riku Rauhala 79119477b3 [Backend] Use ExtentCode in facultyBasics 2024-07-16 08:23:23 +03:00
Riku Rauhala 224feb18d6 [Backend] Refactor graduatedStudyrights 2024-07-16 08:21:55 +03:00
Riku Rauhala d96411fe69 [Backend] Refactor isNewProgramme 2024-07-15 21:47:40 +03:00
Riku Rauhala 843fe84c13 [Backend] Refactor startedStudyrights 2024-07-15 21:31:36 +03:00
Riku Rauhala 5a52e03d52 [Backend] Fix a broken query for inside transfers 2024-07-15 21:02:38 +03:00
Riku Rauhala 26dfa2dcec [Backend] Install Umzug types 2024-07-15 20:25:11 +03:00
Riku Rauhala 75c6fb4739 [Updater] Enable logging colors 2024-07-15 20:25:11 +03:00
Valtteri Kantanen dcdf6f5848 [Updater] Fix education being used as degree programme
It seems that all needed programmes can now be found from `modules` table and there's no need to use `educations`. This also fixes the bug where some study rights got a code like 'KM-TIETOJENK-KOUL' even though it's not a degree programme but an education
2024-07-15 18:22:19 +03:00
Riku Rauhala e32a32ad54 [Backend] Use ExtentCode in facultyGraduationTimes 2024-07-15 16:03:09 +03:00
Riku Rauhala 238557ebfb [Backend] Enable colors for logger 2024-07-15 15:05:14 +03:00
Riku Rauhala ddee43a6a3 [Backend] Add source mapping to tsconfig 2024-07-15 14:25:08 +03:00
Riku Rauhala 42edf79a39 [Faculty programmes] Fix programmes with empty rows 2024-07-15 13:49:08 +03:00
Riku Rauhala 55ee912e56 [Faculty programmes] Hide tables with 0 statistics 2024-07-15 13:13:46 +03:00
Riku Rauhala 71c6622767 [Backend] Move config to src 2024-07-15 12:43:14 +03:00
Valtteri Kantanen 1733879a24 [Backend] Fix type error that happened during a restart 2024-07-15 12:36:54 +03:00
Valtteri KantanenandGitHub 3542e6df57 Merge pull request #4567 from UniversityOfHelsinkiCS/OOD-24
[Updater] Removed organisation id from semester handling
2024-07-15 12:17:28 +03:00
Valtteri Kantanen 0948af41f9 [Updater] Remove unused parameter from getStudyRightSemesterEnrollments 2024-07-15 12:08:21 +03:00
Matti Räsänen 39af9ac937 [FD configs] Edited fd compose frontend volumes 2024-07-15 10:13:18 +03:00
EssKayzandGitHub 787c67a5ff Merge branch 'master' into OOD-24 2024-07-15 10:03:33 +03:00
Riku Rauhala d6c0847f6a [Backend] Refactor open uni format functions 2024-07-12 21:14:53 +03:00
Riku Rauhala febcd20a81 [Backend] Create enum EnrollmentType 2024-07-12 21:05:36 +03:00
Riku Rauhala 34cd554e7a [Backend] Create enum Phase 2024-07-12 20:42:11 +03:00
Riku Rauhala be19c456ba [Backend] Extract study programme format functions 2024-07-12 20:38:51 +03:00
Riku Rauhala 95e6e38271 [Backend] Create enum ElementDetailType 2024-07-12 20:03:51 +03:00
Riku Rauhala db9a4b7e78 [Backend] Create enum PriorityCode 2024-07-12 19:50:58 +03:00
Riku Rauhala 85a52731ad [Backend] Extract faculty transfers 2024-07-12 19:42:31 +03:00
Riku Rauhala a62dfc81b3 Revert "[Backend] Use ExtentCode in all remaining places"
This reverts commit bef2482759.
2024-07-12 19:24:53 +03:00
Riku Rauhala bef2482759 [Backend] Use ExtentCode in all remaining places 2024-07-12 17:36:40 +03:00
Matti Räsänen 2aaa6b590a [Git] Added enviroments to gitignore 2024-07-12 16:10:36 +03:00
EssKayz e64f453386 [FD-Compose] Cleanup nodemod volume bind 2024-07-12 15:52:11 +03:00
Riku Rauhala f7a782aea7 [Backend] Await faculties 2024-07-12 15:35:11 +03:00
Riku Rauhala b32ea59ad5 [Backend] Use acual date types for date attributes 2024-07-12 14:59:06 +03:00
Riku Rauhala 2994c80e97 [Backend] Fix broken import 2024-07-12 14:55:07 +03:00
Riku RauhalaandGitHub b441a688dc Merge pull request #4571 from UniversityOfHelsinkiCS/aws-rds-compatibility
[Updater][Backend] AWS RDS compatibility
2024-07-12 14:46:15 +03:00
EssKayz 547f077538 [backend][migrations] Remove ALTER TABLE owner postgres
This makes it easier for DBA to manage the roles for database
2024-07-12 14:28:35 +03:00
EssKayz ea4a730ec1 [backend][migrations] Remove Extension comment
This comment doesn't mechanically do anything, but requires super user to complete in RDS so no real reason to try to circumvent the problem otherwise
2024-07-12 14:27:12 +03:00
EssKayz b421e8a9eb [updater] allow self-signed certificates for RDS connectins 2024-07-12 14:26:08 +03:00
Riku Rauhala 0b4046b061 [Backend] Increase the usage of ExtentCode 2024-07-12 14:17:34 +03:00
Riku RauhalaandGitHub d213b927a4 Merge pull request #4570 from UniversityOfHelsinkiCS/frontend-service-provider-env-fix
[Frontend] Add REACT_APP_ prefix to SP
2024-07-12 11:25:54 +03:00
EssKayz a3d1b992b5 [Frontend] Add REACT_APP_ prefix to SP 2024-07-12 11:01:49 +03:00
Riku Rauhala d84544d070 [Backend] Use ExtentCode in facultyStudentProgress 2024-07-12 09:05:00 +03:00
Riku Rauhala 14646e3bb2 [Backend] Use ExtentCode in faculty service 2024-07-11 21:47:38 +03:00
Riku Rauhala 64f7bb99ae [Backend] Extract faculty format functions 2024-07-11 21:40:22 +03:00
Riku Rauhala 84cdf29e4c [Backend] Use ExtentCode in facultyHelpers 2024-07-11 21:12:48 +03:00
Riku Rauhala 4262229856 [Backend] Refactor Faculty/Organization logic 2024-07-11 21:02:33 +03:00
Riku Rauhala 5a43e40196 [Backend] Use ExtentCode in facultyHelpers 2024-07-11 20:26:55 +03:00
Riku Rauhala daad45264f [Backend] Use enum ExtentCode in providerCredits service 2024-07-11 20:03:34 +03:00
Riku Rauhala 6e081961cb [Backend] Refactor and type graduationHelpers 2024-07-11 19:31:20 +03:00
Riku Rauhala 93c7c84d87 [Backend] Create enum ExtentCode 2024-07-11 18:55:49 +03:00
Riku Rauhala 539c77fdde Change Renovate rebasing rules 2024-07-11 15:39:16 +03:00
ShootingStar91 022ebb3cc5 Try to fix tsconfig.json 2024-07-11 15:05:13 +03:00
ShootingStar91 0e1e2a5959 Remove npm prune 2024-07-11 14:29:23 +03:00
ShootingStar91 559c659a16 Modify dockerfile after js-files are included by tsc 2024-07-11 14:25:55 +03:00
ShootingStar91 8b27e91a83 AllowJS and fix ts error that it caused 2024-07-11 14:25:27 +03:00
Riku Rauhala b269dfe995 [Backend] Add missing AutoIncrement decorators 2024-07-11 13:59:04 +03:00
Riku Rauhala 880bce2c03 [Backend] Add missing semestercode to Credit model 2024-07-11 13:44:28 +03:00
ShootingStar91 add8e4f7c8 remove sql logging 2024-07-11 13:04:05 +03:00
ShootingStar91 4d4fcef3ef Try fix insidious seuqlize where bug 2024-07-11 13:01:04 +03:00
Riku Rauhala 5bffa46cbf [Backend] Move SIS_DB_URL to conf 2024-07-11 10:09:38 +03:00
Riku Rauhala d73ae52501 [Backend] Rename studentStudentnumber back to student_studentnumber 2024-07-11 10:05:49 +03:00
Riku Rauhala 448d3668fd [Study programme route] Add error handling to Grafana logging 2024-07-10 20:09:31 +03:00
Riku Rauhala d69784af32 [Backend] Add @AutoIncrement decorator to models with bigint primary key 2024-07-10 15:48:32 +03:00
Riku Rauhala 792bf911c0 [Custom population search service] Fix search 2024-07-10 15:47:04 +03:00
Riku Rauhala df87abc0ee [Student service] Fix crashing 2024-07-10 14:21:02 +03:00
Riku Rauhala 9340efe406 [Backend] Create enum GenderCode 2024-07-10 13:50:26 +03:00
Riku Rauhala 3a1e155b11 Merge remote-tracking branch 'origin/master' into tsMerge 2024-07-10 13:12:35 +03:00
Matti Räsänen 5086734db3 [Updater] Removed organisation id from initStartYearToSemesters and getSemester functions. Removed ORG_TO and orgTo prefixes from redis key and localMaps 2024-07-10 12:44:45 +03:00
Riku Rauhala 0a79ac735f [Backend] Remove npm prune from Dockerfile 2024-07-10 11:04:50 +03:00
Riku Rauhala 255ab0de1f [Backend] Include dev dependencies in build process 2024-07-10 10:58:54 +03:00
Riku Rauhala 14ef484b7a [Backend] Add build command 2024-07-10 10:56:05 +03:00
Riku Rauhala 1d26819db9 [Backend] Update Dockerfile 2024-07-10 10:16:21 +03:00
Riku Rauhala bf3a500e58 [Backend] Update Dockerfile 2024-07-10 10:12:59 +03:00
Riku Rauhala 72d846d3b9 [Backend] Update Dockerfile 2024-07-10 10:09:11 +03:00
Matti Räsänen 93ada9edd0 [Docker] removed sis-importer-db-data volume from fd compose file 2024-07-10 08:18:40 +03:00
Matti Räsänen 1f195e0697 Merge branch 'master' into OOD-24 2024-07-10 07:47:10 +03:00
Riku Rauhala aa60d86993 [Population service] Fix TypeScript issues 2024-07-09 18:20:15 +03:00
Riku RauhalaandGitHub b692137207 Merge pull request #4566 from UniversityOfHelsinkiCS/OOD-34
[Updater] Added fallback to abbreviation in function initGradeScaleIdToGradeIdsToGrades
2024-07-09 18:15:02 +03:00
Riku Rauhala cadffa6b03 [Student service] Fix typing issues and update exports 2024-07-09 18:11:07 +03:00
Riku Rauhala f804c3295a Add tsc command 2024-07-09 16:23:05 +03:00
Riku Rauhala 7d8bd40ab3 Install @types/lodash 2024-07-09 16:16:55 +03:00
Riku Rauhala 79a2b2ca2c Ignore dist 2024-07-09 16:15:07 +03:00
EssKayz a8e6f5ac43 [updater] Add configurability of port to knex conn 2024-07-09 16:00:01 +03:00
EssKayz 43c9c1ad85 [fd-compose] Make connection to importer side db 2024-07-09 15:54:13 +03:00
Matti Räsänen 4109a840cb [Updater] Added fallback to abbreviation in function initGradeScaleIdToGradeIdsToGrades 2024-07-09 14:51:18 +03:00
Riku Rauhala e48e5ba853 Format code 2024-07-09 12:21:17 +03:00
Riku Rauhala ddd8ecf5aa Run CI for the branch tsMerge 2024-07-09 11:34:56 +03:00
Riku Rauhala 6f9fdf9f6f Merge remote-tracking branch 'origin/master' into tsMerge 2024-07-09 10:36:03 +03:00
Riku Rauhala dacb0cec03 [Students] Prevent crashing for non-existent student number 2024-07-09 10:33:00 +03:00
Riku Rauhala 1e63739c41 [Bachelor Honours] Use consistent spelling 2024-07-09 10:24:38 +03:00
Riku Rauhala 6adf5cf583 Fix close to graduation 2024-07-08 20:51:57 +03:00
Riku Rauhala fead93529d Merge remote-tracking branch 'origin/master' into tsMerge 2024-07-08 17:13:59 +03:00
Riku Rauhala 524c92f098 Update models 2024-07-08 17:13:51 +03:00
Riku Rauhala f3197f2d75 Update kone and user model imports 2024-07-08 14:45:15 +03:00
Riku Rauhala 2adef388ef Update models
Add missing fields, rearrange to group closely related fields, fix incorrect datatypes
2024-07-08 12:01:03 +03:00
Riku RauhalaandGitHub 26755bbdfe Merge pull request #4563 from UniversityOfHelsinkiCS/OOD-22
[Backend] Added ignoredFacultyCodes to facultyCodes
2024-07-08 11:33:07 +03:00
Matti Räsänen aa71c8cb1f [Backend] Renamed allFacultyCodes to facultyCodes 2024-07-08 10:31:24 +03:00
Riku Rauhala 5badb32fd8 Add types to the User model 2024-07-05 17:49:40 +03:00
Valtteri Kantanen 3a0d16aae8 Fix formatting for BullMQ job durations 2024-07-05 15:14:58 +03:00
Riku Rauhala d0b30e8c38 Add types for kone models 2024-07-05 14:56:32 +03:00
Matti Räsänen d41877fe52 [Backend][analyticsService] Filtering out ignoredFacultyCodes from allFacultyCodes 2024-07-05 13:15:23 +03:00
Riku Rauhala 4f00ca52bd Merge remote-tracking branch 'origin/master' into tsMerge 2024-07-05 09:55:28 +03:00
Riku Rauhala 09fe88bd7d Extract enum CreditTypeCode 2024-07-05 09:25:16 +03:00
Valtteri Kantanen 032c9463dc Add better logging for BullMQ jobs 2024-07-04 16:28:33 +03:00
Valtteri Kantanen 6000ac9f3e Send errors from study programme and faculty refresh jobs to Sentry 2024-07-04 16:28:08 +03:00
Riku Rauhala fa1c23a731 Replace CREDIT_TYPE_CODES with enum CreditTypeCode 2024-07-04 15:40:00 +03:00
Riku Rauhala 3d2dd2b77a Sort imports and format code 2024-07-04 15:40:00 +03:00
Valtteri Kantanen b8e37ce791 [Study programme overview] Fix transferred stats calculation for combined programme 2024-07-04 15:21:40 +03:00
Valtteri Kantanen 6a5f8afd4e Add possibility to remove waiting jobs from BullMQ queue in the Updater view 2024-07-04 14:06:10 +03:00
Matti Räsänen 8dcc9e60a7 [Backend] Updated facultyCodes to organisationConstants 2024-07-04 13:21:13 +03:00
ShootingStar91 1a66308148 Fix faulty columns 2024-07-04 13:05:52 +03:00
Matti Räsänen a1a4f5e426 Merge branch 'master' into OOD-22 2024-07-04 12:42:54 +03:00
Matti Räsänen 892f428ee2 [Backend] Added ignoredFacultyCodes to facultyCodes module 2024-07-04 12:42:28 +03:00
Riku RauhalaandGitHub e630693376 Merge pull request #4562 from UniversityOfHelsinkiCS/OOD-31
[Backend][Updater] Renamed facultyCodes to organisationConstants and moved universityOrgId there
2024-07-04 12:31:46 +03:00
Riku Rauhala 1af902569c [Updater] Rename hyStudyModules to organizationStudyModules 2024-07-04 11:58:29 +03:00
ShootingStar91 ea84c668c7 Fix missing/faulty columns in models 2024-07-04 11:55:47 +03:00
ShootingStar91 fd7a34fd39 Fix broken import in studets service 2024-07-04 11:55:32 +03:00
Valtteri Kantanen 92aa1d5120 [Study programme overview] Only include graduations from correct years 2024-07-04 11:51:32 +03:00
Riku Rauhala ee43ec89ac Use consistent spelling of licentiate 2024-07-04 10:56:40 +03:00
Valtteri Kantanen c88029c5a1 [Population statistics] Try to fix tests 2024-07-03 18:17:52 +03:00
Valtteri Kantanen 3dd40cbec9 Change completed_credits in studyplan table from an integer into a double 2024-07-03 17:17:00 +03:00
Valtteri Kantanen 7d9076317c [Students] Make 'secondary' labels smaller 2024-07-03 15:08:34 +03:00
Valtteri Kantanen bdc3dd19c4 Add indexes to sis_study_rights and sis_study_right_elements tables in sis-db 2024-07-03 15:07:46 +03:00
Matti Räsänen fb728d5796 [Backend][Updater] Removed universityOrgId from organisationConstans and added it to updater config file. Refactored updater to use it from config. 2024-07-03 12:41:25 +03:00
Valtteri Kantanen a20887e5ca [Study programmes] Rename isOldOrObsolete to isRelevantProgramme 2024-07-03 11:54:26 +03:00
Riku Rauhala 1703712e48 [Documentation] Fix a typo 2024-07-03 11:30:52 +03:00
Riku Rauhala 583685f8af [Documentation] Add phase to numeric_types.md 2024-07-03 11:29:48 +03:00
Matti Räsänen ea21b08a9e [Backend][Updater] Renamed facultyCodes to organisationConstants and moved universityOrgId there. Refactored updater to use universityOrgId from new location organisationConstants 2024-07-03 11:22:08 +03:00
Valtteri Kantanen 85c662c939 [Study programme overview] Make getStartDate function simpler, it doesn't need study programme 2024-07-03 11:11:24 +03:00
Valtteri Kantanen 04c78d4c15 [Updater] Remove study track from SISStudyRightElement if it's not in a newer snapshot with the same programme 2024-07-03 10:44:43 +03:00
Valtteri Kantanen a87098210d [Updater] Add missing study track codes to studyTrack field of SISStudyRightElement 2024-07-03 10:43:58 +03:00
Valtteri Kantanen 20cc1c8407 [Study programme overview] Remove extra parameters from functions 2024-07-03 10:42:21 +03:00
Riku Rauhala ad7cb80ca7 [Documentation] Update numeric types
Add missing types and their explanations, format nicely
2024-07-02 16:50:10 +03:00
Valtteri Kantanen dfc6ab4739 [Study programme overview] Fix tests 2024-07-02 16:14:09 +03:00
Valtteri Kantanen 3bbb9916c7 [Study programme overview] Fix tests 2024-07-02 15:59:21 +03:00
Valtteri Kantanen fe822d0bd5 [Study programme overview] Use new models to calculate average graduation times 2024-07-02 15:39:25 +03:00
Valtteri Kantanen f1c8e955c5 [Study programme overview] Remove duplicated code 2024-07-02 11:19:48 +03:00
Valtteri Kantanen f4cf046958 [Close to graduation] Fix semesters present 2024-07-02 11:18:06 +03:00
Valtteri Kantanen 5dfee0c538 [Study programme overview] Fix tests 2024-07-01 17:26:21 +03:00
Valtteri Kantanen 55f2cca6c9 [Study programme overview] Use new models in transferred away/to stats 2024-07-01 17:11:50 +03:00
Valtteri Kantanen 76583491b9 [Study programme overview] Use new models to calculate graduation stats 2024-07-01 15:31:09 +03:00
Valtteri Kantanen 78c1ae84ea [Update] Fix SISStudyRightElements with earlier endDate then startDate 2024-07-01 15:24:46 +03:00
Valtteri Kantanen 5109174b26 [Updater] Add degreeProgrammeType to ProgrammeModules 2024-07-01 12:25:26 +03:00
Valtteri Kantanen 34b297de4e [Updater] Add degreeProgrammeType to SISStudyRightElements 2024-07-01 11:49:31 +03:00
Valtteri Kantanen 9f70c7b8f0 [Study programme overview] Simplify handling of progress criteria 2024-07-01 10:54:06 +03:00
Valtteri Kantanen 630fedc9ab Update local jami-db to postgres 15 2024-07-01 10:54:06 +03:00
Valtteri Kantanen 51a40c75e7 [Students] Fix page crashing 2024-07-01 10:54:06 +03:00
Riku Rauhala a0642b515b [Backend] Extract function isOldOrObsolete
Eliminating copy-paste
2024-07-01 10:29:39 +03:00
arttu fc69f74264 Fix couple type errors 2024-06-28 16:24:41 +03:00
Riku Rauhala 0d385d003b [Navigation bar] Remove unnecessary className 2024-06-28 16:21:39 +03:00
Valtteri Kantanen 70308afa27 Give Sentry DSN as an env variable during build 2024-06-28 16:09:40 +03:00
arttu 1298b90604 Merge some more changes 2024-06-28 16:09:20 +03:00
Riku Rauhala 17c110cf28 Remove version field from docker-compoes files
The version field is obsolete and using it leads to console warnings
2024-06-28 16:02:12 +03:00
arttu ae273e846d Merge master to ts 2024-06-28 15:55:28 +03:00
Riku Rauhala 449c1932c6 Simplify docker-compose.test.yml 2024-06-28 15:50:35 +03:00
Valtteri Kantanen f8a1a547d7 [University view] Fix typo in programme filter 2024-06-28 15:12:01 +03:00
Riku Rauhala 61e487bd6b [Navigation bar] Attach a 'dev' label to the logo when in dev mode 2024-06-28 15:05:19 +03:00
Valtteri Kantanen 13535ba3f6 [Custom population] Fix tests 2024-06-28 14:59:12 +03:00
Valtteri Kantanen 317c4594c3 [Custom population] Allow commas, semicolons and spaces as separator for student numbers 2024-06-28 14:41:58 +03:00
Valtteri Kantanen 6064fe9514 [Custom population] Fix page crashing if no mathing study right is found 2024-06-28 10:57:20 +03:00
Valtteri Kantanen d49eb08bae [Study programme overview] Bring back new calculations that were deleted in aebfb0e 2024-06-28 10:42:07 +03:00
Riku Rauhala 880674b988 [Backend] Replace getAllProgrammes 2024-06-27 22:04:50 +03:00
Riku Rauhala 39a8f9eaee [Redux] Split useFilteredAndFormattedStudyProgrammes into smaller functions 2024-06-27 22:04:50 +03:00
Riku Rauhala 9c065e04fb [StudyProgramme] Replace ElementDetail with SISStudyRightElement 2024-06-27 22:04:50 +03:00
Riku Rauhala a563ee474f Replace ElementDetails 2024-06-27 22:04:50 +03:00
Riku Rauhala aebfb0e2c9 [Backend] Rename studyProgramme services 2024-06-27 22:04:50 +03:00
Valtteri Kantanen c036e3b626 [Study programme overview] Update tests 2024-06-27 15:20:52 +03:00
Valtteri Kantanen ef3b8c0baa [Study programme overview] Use new models to calculate 'Started studying' and 'Accepted' numbers 2024-06-27 14:56:48 +03:00
Valtteri Kantanen 57129b91fe [Study programme overview] Remove extent code filter from study right query 2024-06-27 14:55:15 +03:00
Valtteri Kantanen 451bc495ee Change Sentry DSN into an environment variable 2024-06-27 13:35:38 +03:00
Riku Rauhala 64f9e61431 [Code Climate] Allow higher method complexity
From what I've seen this setting is quite strict, let's allow a little bit more complexity
2024-06-27 09:37:29 +03:00
Riku Rauhala 4d4fa4d0e2 [Code Climate] Ignore more files 2024-06-27 09:28:14 +03:00
Riku Rauhala 8385077ab0 [Code Climate] Ignore more files 2024-06-27 09:23:49 +03:00
Riku Rauhala 74d2baa9f9 [Code Climate] Ignore more files 2024-06-27 09:17:25 +03:00
Riku Rauhala 2916b4153d Create Code Climate config 2024-06-27 09:09:18 +03:00
Riku Rauhala dd484d7207 [Backend] Refactor updateCreditCriteriaInfo 2024-06-26 19:38:32 +03:00
Riku Rauhala b523aab3b6 [Backend] Refactor populations functions 2024-06-26 16:10:12 +03:00
Valtteri Kantanen 2bb1af35d3 [Study programme overview] Use SISStudyRights to determine next programme after bachelor's programme 2024-06-26 15:55:43 +03:00
Riku RauhalaandGitHub f75fc169a7 Merge pull request #4556 from UniversityOfHelsinkiCS/university-view-generalization
[Backend] Make H50 configurable
2024-06-26 15:51:49 +03:00
Valtteri Kantanen 249fb6f20a [Students] Fix error caused by unavailable course data 2024-06-26 15:27:10 +03:00
Valtteri Kantanen 8bba2d8842 [Updater] Fix logic for end date of study right elements 2024-06-26 12:43:08 +03:00
Riku Rauhala a492b14a14 [Progress tab] Refactor to reduce copy-paste 2024-06-26 12:04:02 +03:00
Riku Rauhala 5010e65ea9 [Frontend] Remove duplicate date format constant 2024-06-26 12:04:02 +03:00
Riku Rauhala d216069df6 [Frontend] Move timeAndDate to util 2024-06-26 12:04:02 +03:00
Valtteri Kantanen 47bb1f5d61 [Study programme overview] Use SISStudyRights to determine previous programme before master's programme 2024-06-26 11:29:38 +03:00
Valtteri Kantanen 217bca5153 [Backend] Fix foreign keys used by models 2024-06-26 11:22:36 +03:00
EssKayz a03e535eb3 Python programmer making his snake into a camel 2024-06-26 10:58:32 +03:00
Valtteri KantanenandGitHub e5dd44b657 Merge pull request #4557 from UniversityOfHelsinkiCS/thesis-urns-expansion
[Backend] Add more thesis type urns
2024-06-26 10:33:30 +03:00
Valtteri KantanenandGitHub f45846b1a3 Merge branch 'master' into thesis-urns-expansion 2024-06-26 10:25:12 +03:00
Valtteri Kantanen b300a6a131 Make thesis type urns university-specific 2024-06-26 10:22:05 +03:00
Riku Rauhala 286c778756 Use named imports for lodash 2024-06-25 22:24:28 +03:00
Riku Rauhala 8f686200ca [Teachers] Fix crashing 2024-06-25 21:27:39 +03:00
Riku Rauhala 0e2c5462f6 Refactor mapToProviders 2024-06-25 20:36:36 +03:00
Riku Rauhala e86b327cfe [Backend] Rename snake_case files to camelCase 2024-06-25 16:34:54 +03:00
Riku Rauhala 6c964ce575 [Backend] Rename err variables
Let's use error for consistency with the rest of the code base
2024-06-25 16:34:54 +03:00
Riku Rauhala 7f555e72df [Backend] Refactor faculty 2024-06-25 16:34:54 +03:00
Riku Rauhala 7178c3ee0d [Backend] Refactor mapObject 2024-06-25 16:34:54 +03:00
Riku Rauhala 9406c6644d [Backend] Refactor mapToProviders 2024-06-25 16:34:53 +03:00
Riku Rauhala b70fe4f3bc [Backend] Organize utils 2024-06-25 16:34:53 +03:00
EssKayz eed77be183 [Backend] Add more thesis type urns 2024-06-25 15:44:42 +03:00
EssKayz afd38f4f91 [Backend] Make H50 configurable 2024-06-25 15:31:36 +03:00
Valtteri Kantanen 88d3536d6a [Study programme overview] Don't fetch the same student numbers again
No need to fetch them again as they've already been determined with `getCorrectStudentnumbers`. This also caused some students to be counted twice in the statistics (Studytracks and class statistics tab, column 'All')
2024-06-25 13:25:39 +03:00
Riku Rauhala 98b7ebe5d5 [Backend] Refactor openUniHelpers 2024-06-25 09:38:19 +03:00
Riku Rauhala c1eee9f175 [Open uni] Refactor one more time 2024-06-25 09:20:06 +03:00
Valtteri Kantanen 66ee9b8a3f [Students] Fix tests 2024-06-24 18:10:17 +03:00
Valtteri Kantanen e607d348e2 [Students] Add a test for Bachelor Honours visibility 2024-06-24 17:48:20 +03:00
Valtteri Kantanen 3079039d5d [Students] Fix Bachelor Honours not showing 2024-06-24 17:40:44 +03:00
Riku Rauhala 8d6a8be91f [Open uni] Refactor 2024-06-24 15:44:07 +03:00
Riku Rauhala 8a124cae9a [Open uni] Refactor filter logic 2024-06-24 15:44:07 +03:00
Riku Rauhala 74343af176 [Open uni] Big refactor 2024-06-24 15:44:07 +03:00
Riku Rauhala 5e7c8628c3 [Backend] Refactor 2024-06-24 15:44:07 +03:00
Valtteri Kantanen 462418c3eb [Course statistics] Big refactor 2024-06-24 14:28:24 +03:00
Riku Rauhala 8e2b7b2ce1 [Language center] Big refactor 2024-06-24 13:28:33 +03:00
Valtteri Kantanen 7b6c7aeecb [Course stats] Remove duplicated code 2024-06-24 13:10:58 +03:00
Valtteri Kantanen b1f34479eb Use SISStudyRight model to find students by programme code 2024-06-24 11:03:48 +03:00
Valtteri Kantanen 56e2462d30 Remove unused code 2024-06-24 10:52:02 +03:00
Valtteri Kantanen f7372e8125 Update axios from 0.27.2 to 0.28.1 2024-06-20 14:30:18 +03:00
Valtteri Kantanen a9f6cbe36e Change axios version from 0.28.0 to 0.27.2 2024-06-20 13:44:42 +03:00
Valtteri Kantanen 881e48f76c Update axios from 0.21.4 to 0.28.0 2024-06-20 13:27:05 +03:00
Valtteri KantanenandGitHub 0939e9129a Merge pull request #4553 from UniversityOfHelsinkiCS/fix-konedb-migrations
[Backend] Fix 20190821 kone-db migration
2024-06-20 12:39:26 +03:00
Valtteri KantanenandGitHub cb396623c6 Merge pull request #4552 from UniversityOfHelsinkiCS/fix-fix-migration
[Backend] Fix fix_faculty_code_constraint migration
2024-06-20 12:37:41 +03:00
Valtteri Kantanen 8716306083 Compress backend responses 2024-06-20 12:22:15 +03:00
Valtteri Kantanen 048ba916e4 Fix tests 2024-06-20 12:21:22 +03:00
Valtteri Kantanen c94549d0d3 [Students] Big refactor 2024-06-20 11:51:27 +03:00
Valtteri Kantanen 606ca3bfd5 [Updater] Remove manual fixing of graduations, they are already correct in snapshots 2024-06-20 11:36:26 +03:00
EssKayz 040a4de536 [Backend] Fix 20190821 kone-db migration 2024-06-20 10:55:37 +03:00
Riku Rauhala ec47d63c1b Extract time and date related common functions 2024-06-19 20:47:52 +03:00
Riku Rauhala bcad45a84b Use constants for ISO dates 2024-06-19 20:02:13 +03:00
EssKayz 91184ef9d6 [Backend] Fix fix_faculty_code_constraint migration 2024-06-19 16:08:50 +03:00
Riku Rauhala b946a9e87f [Backend] Refactor 2024-06-19 15:32:10 +03:00
Riku Rauhala cdde42e7d5 Use improved constants for dates 2024-06-19 14:55:53 +03:00
Riku Rauhala bcb115d648 Remove an unused function 2024-06-19 14:14:49 +03:00
Riku Rauhala d848030c6a [Class statistics] Remove combined Excel 2024-06-19 14:04:07 +03:00
Riku Rauhala c4cf9ba056 Rename variables 2024-06-19 11:43:06 +03:00
Riku Rauhala 93aabb97c5 [Courses tab] Include Hyv. grades in Excel 2024-06-19 10:39:11 +03:00
Riku RauhalaandGitHub 603774b287 Merge pull request #4550 from UniversityOfHelsinkiCS/facultycode-refactor
[Backend] Extract facultyCodes to separate file
2024-06-18 21:30:41 +03:00
Riku Rauhala d3e484100a [Courses tab] Fix study guidance groups population 2024-06-18 21:10:01 +03:00
Riku Rauhala 9f7f294fe1 [Backend] Remove filtering coursestatistics 2024-06-18 14:43:57 +03:00
EssKayz 2be9c3b47c [Backend] Extract facultyCodes to separate file 2024-06-18 14:21:52 +03:00
Riku Rauhala 79a43aae48 [Courses tab] Revert back to old logic for substitutions 2024-06-18 14:15:12 +03:00
Riku Rauhala 4859ab197a [Backend] Refactor allStudents 2024-06-18 14:15:12 +03:00
Riku Rauhala f155b13995 [Backend] Rename variables with typos 2024-06-18 14:15:12 +03:00
Riku Rauhala 76f2c2a276 Rename variables 2024-06-18 14:15:12 +03:00
Valtteri Kantanen e66aa244d6 Merge branch 'big-refactor-close-to-graduation' 2024-06-18 10:55:00 +03:00
Valtteri Kantanen cd5af9571a [Close to graduation] If a student has more then one primary study plan that qualifies, show them all 2024-06-18 10:54:11 +03:00
Riku Rauhala 9ca473ca8e [Documentation] Fix typos 2024-06-17 22:09:55 +03:00
Riku RauhalaandGitHub f9b9d7ed53 Update README.md
Add an emoji for tietosuoja too
2024-06-17 22:04:49 +03:00
Riku Rauhala a8ad765dc6 Refactor ProgressTab
Make it more readable and eliminate some copy-paste
2024-06-17 21:35:26 +03:00
Riku Rauhala 7cbc11a3e5 [Backend] Refactor bottlenecksOf.js 2024-06-17 20:14:52 +03:00
Valtteri Kantanen 2813afb625 [Students] Allow search terms that are at least three characters long 2024-06-17 14:44:42 +03:00
Valtteri Kantanen bbe1ee899a [Students] Remove unused functions 2024-06-17 14:44:42 +03:00
Valtteri Kantanen bda81c8b39 Add a separate job for updating close to graduation data 2024-06-17 14:44:42 +03:00
Valtteri Kantanen 7abd945c5d Remove functionality for updating students individually (#4489) 2024-06-17 14:44:42 +03:00
Riku Rauhala 5f332344d6 [Courses tab] Rename show substitutions to include substitutions 2024-06-17 14:04:22 +03:00
Riku Rauhala 832546cd73 [Courses tab] Refactor getPassedStudents
Combine the functions to reduce copy-paste
2024-06-17 13:59:19 +03:00
Riku Rauhala a23c638416 [Courses tab] Include completion date for courses with grades 2024-06-17 13:34:45 +03:00
Riku Rauhala e9bd6ceae9 [Courses tab] Refactor substitution passed logic 2024-06-17 12:39:52 +03:00
Valtteri Kantanen 40079bf963 [Completed courses] Add missing secondaryEmail field 2024-06-17 12:39:09 +03:00
Valtteri Kantanen 44ffcf878d [Updater] Fix some SISStudyRightElements not being parsed correctly 2024-06-17 09:55:23 +03:00
Riku Rauhala 29bd2c8ab5 [Courses tab] Refactor hasPassed 2024-06-14 17:01:13 +03:00
Valtteri Kantanen 3ca2d6934c [Teachers] Fix and improve tests 2024-06-14 13:46:44 +03:00
Riku Rauhala e75fc3c6ae [Courses tab] Check if subststitutions are shown 2024-06-14 13:39:11 +03:00
Valtteri Kantanen bce4e333c5 [Teachers] Try to make searches more efficient 2024-06-14 13:23:24 +03:00
Riku Rauhala bc951800d5 [Courses tab] Include substitutions in the summary row 2024-06-14 11:25:09 +03:00
Riku Rauhala 505ea3254c [Courses tab] Use the new logic for checking substitution course passed 2024-06-14 11:25:09 +03:00
Riku Rauhala b75bf7cbbf [Courses tab] Include substitutions in total passed 2024-06-14 11:25:09 +03:00
Riku Rauhala da6aeb2cb4 [Course tab] Refactor getPassedStudents 2024-06-14 11:25:09 +03:00
Riku Rauhala 3b33c95625 [Progress tab] Refactor 2024-06-14 11:25:08 +03:00
Riku Rauhala 5348e86bd2 Reduce copy-paste 2024-06-14 11:25:08 +03:00
Valtteri Kantanen 557663e5e1 [Backend] Remove unused code and move splitByEmptySpace function to utils 2024-06-13 17:05:32 +03:00
Valtteri Kantanen d4073a836c Update some programme codes 2024-06-13 15:27:42 +03:00
Riku Rauhala e8ad1bb08d [Population statistics] Update iinfobox texts 2024-06-13 09:58:11 +03:00
Riku Rauhala 75195de6cc [StudentInfoItem] Remove unused parameters
Parameters tab and view are no longer used
2024-06-12 15:23:04 +03:00
Riku Rauhala 3de924f6a6 [Courses tab] Rename mandatory courses
The courses are really not mandatory. Instead, the courses are part of the programme's curriculum
2024-06-12 15:18:25 +03:00
Valtteri Kantanen f9ab5f57fd [Close to graduation] Big refactor 2024-06-12 13:06:59 +03:00
Valtteri Kantanen 05f7204863 Add associations for SISStudyRight and SISStudyRightElement 2024-06-12 13:05:50 +03:00
Riku Rauhala 75b20c9750 [Courses tab] Enable the Show substitutions toggle 2024-06-12 12:51:28 +03:00
Valtteri Kantanen 346b4a29c7 Add sis_study_right_id to studyplan table 2024-06-12 12:00:14 +03:00
Valtteri Kantanen 7011849143 [Updater] Fix error caused by education not being found by id 2024-06-12 10:43:19 +03:00
Valtteri Kantanen 5ee2c3a9c9 [Study programme overview] Fix tests 2024-06-12 10:31:06 +03:00
Valtteri Kantanen 5b2649c1bf [Faculty statistics] Display graph and table side by side if they fit 2024-06-12 10:14:12 +03:00
Valtteri Kantanen 14c1de6a38 [Faculty statistics] Change 'special' to 'separate' so that credits show up correctly 2024-06-12 10:11:23 +03:00
Valtteri Kantanen 5a96a08e68 [Faculty statistics] Use Highcharts exports instead of own xlsx implementation 2024-06-11 20:07:53 +03:00
Riku Rauhala 4c700b7043 [Students table] Add the Combine substitutions toggle 2024-06-11 19:40:16 +03:00
Riku Rauhala a4e1afcc1c [Courses tab] Take the enrollments into account when sorting by a course 2024-06-11 19:40:16 +03:00
Riku Rauhala 4ade93b4d7 [Courses tab] Display gray checkmarks for substituted grades 2024-06-11 19:40:16 +03:00
Riku Rauhala ebd05a11be [Courses tab] Update tooltips 2024-06-11 19:40:16 +03:00
Riku Rauhala 86d2b85e21 [Courses tab] Refactor to make the code more readable 2024-06-11 19:40:16 +03:00
Riku Rauhala 15e940b77b Combine .gitignore 2024-06-11 19:40:16 +03:00
Riku Rauhala ad562b45b7 [Courses tab] Add icons for courses with enrollments 2024-06-11 19:40:16 +03:00
Valtteri Kantanen 390ff61162 Get rid of console-filling defaultProps warnings 2024-06-11 17:14:58 +03:00
Valtteri Kantanen ed44f617c0 [Faculty statistics] Fix tests 2024-06-11 16:16:24 +03:00
Valtteri Kantanen 9e990023b7 Add exporting and exportData modules for Highcharts 2024-06-11 15:38:50 +03:00
Valtteri Kantanen 7575dc85a3 Update braces from 3.0.2 to 3.0.3 2024-06-11 12:05:32 +03:00
Valtteri Kantanen c5694840b9 [Updater] Only create study right elements if there's a corresponding study right 2024-06-11 12:05:32 +03:00
Riku RauhalaandGitHub 81146f9866 Merge pull request #4528 from UniversityOfHelsinkiCS/OOD-11
OOD-11: admin can fetch users from Sisu and add to Oodikone user-db
2024-06-11 09:41:51 +03:00
Matti Räsänen cedad01fec OOD-11: Created own users route for fd and moved fd relevant routes there. Add serviceProvider check to routes module 2024-06-11 08:54:00 +03:00
Valtteri Kantanen 1ea162ef7e [Updater] Start updating SISStudyRights and SISStudyRightElements 2024-06-10 17:22:01 +03:00
Valtteri Kantanen 7e69fcc5ee [Updater] Improve logging 2024-06-10 17:22:01 +03:00
Valtteri Kantanen 58f69f50f7 [Updater] Rename studyTracks to studyTrack in SISStudyRightElements 2024-06-10 17:22:01 +03:00
Valtteri Kantanen 8d01562b2d [Updater] Remove facultyCode from SISStudyRightElement 2024-06-10 17:22:01 +03:00
Riku Rauhala 298f119ad3 [Students table] Refactor tabs 2024-06-10 13:03:37 +03:00
Valtteri Kantanen 87f5ffc353 [Updater] Add a new extent code 2024-06-10 11:48:03 +03:00
Jan Rundt 05d4927b3c OOD-11: auth on route and empty roles array 2024-06-10 11:22:17 +03:00
Valtteri Kantanen 9ab9f0ca29 [Updater] Add faculty code to SISStudyRight model 2024-06-10 10:55:31 +03:00
Valtteri Kantanen 6145a76425 [Updater] Extract university organisation id into one place 2024-06-10 10:47:20 +03:00
Riku RauhalaandGitHub 13c86b3259 Merge pull request #4542 from UniversityOfHelsinkiCS/renovate/uuid-10.x
Update dependency uuid to v10
2024-06-10 09:42:54 +03:00
renovate[bot]andGitHub 625ae0cfe3 Update dependency uuid to v10 2024-06-10 06:26:18 +00:00
Riku RauhalaandGitHub 62c8294791 Merge pull request #4537 from UniversityOfHelsinkiCS/renovate/nyc-17.x
Update dependency nyc to v17
2024-06-10 09:15:21 +03:00
renovate[bot]andGitHub d0b7cd8c6c Update dependency nyc to v17 2024-06-10 06:08:22 +00:00
Riku RauhalaandGitHub 65332f5fac Merge pull request #4522 from UniversityOfHelsinkiCS/renovate/highcharts-11.x
Update dependency highcharts to v11
2024-06-10 09:07:35 +03:00
Valtteri Kantanen a6040ceb25 Create new models for studyRight and studyRightElement 2024-06-07 12:15:27 +03:00
Valtteri Kantanen c9adca395c Replace deprecated husky command 2024-06-07 10:37:24 +03:00
Valtteri Kantanen d33ed0653e [Updater] Make handling of attainments clearer 2024-06-07 10:37:24 +03:00
Riku RauhalaandGitHub 251f22bf92 Merge pull request #4533 from UniversityOfHelsinkiCS/renovate/query-string-9.x
Update dependency query-string to v9
2024-06-07 09:29:37 +03:00
Riku RauhalaandGitHub b7cbac6390 Merge pull request #4534 from UniversityOfHelsinkiCS/renovate/major-remark
Update dependency react-markdown to v9
2024-06-07 08:17:06 +03:00
renovate[bot]andGitHub 0d2a568e8c Update dependency react-markdown to v9 2024-06-06 19:08:25 +00:00
Riku RauhalaandGitHub cfa86c5c11 Merge pull request #4521 from UniversityOfHelsinkiCS/renovate/eslint-plugin-cypress-3.x
Update dependency eslint-plugin-cypress to v3
2024-06-06 19:35:48 +03:00
renovate[bot]andGitHub 81d761202d Update dependency query-string to v9 2024-06-06 16:35:34 +00:00
Riku RauhalaandGitHub 4aec52e21b Merge pull request #4527 from UniversityOfHelsinkiCS/renovate/lint-staged-15.x
Update dependency lint-staged to v15
2024-06-06 19:33:35 +03:00
renovate[bot]andGitHub 3fcd366888 Update dependency lint-staged to v15 2024-06-06 16:26:02 +00:00
Riku RauhalaandGitHub fb66ade27b Merge pull request #4523 from UniversityOfHelsinkiCS/renovate/husky-9.x
Update dependency husky to v9
2024-06-06 19:22:20 +03:00
Jan Rundt 0337e86b34 OOD-11: fix to new user section 2024-06-06 16:58:14 +03:00
Jan Rundt 6f92fbdc9a OOD-11: some fixes to new user section 2024-06-06 16:56:43 +03:00
Riku Rauhala ccf4569463 Remove dependabot config 2024-06-05 15:33:45 +03:00
Valtteri Kantanen 1b870de079 Improve logging 2024-06-05 12:56:13 +03:00
Valtteri Kantanen 2f9264b0a0 Prefer regular JS instead of lodash and moment.js in a couple of tests 2024-06-05 12:53:53 +03:00
Jan Rundt 05f182274e OOD-11: no filter or sort for nothing 2024-06-05 10:14:26 +03:00
Jan Rundt a74e495ea5 OOD-11: no filter or sort 2024-06-05 10:09:29 +03:00
Riku Rauhala 9aafd50a66 Update README.md 2024-06-05 09:37:32 +03:00
Jan Rundt 884a4056a3 OOD-11: clean up 2024-06-05 09:25:17 +03:00
Jan Rundt aa46c759e8 OOD-11: using real isDefaultServiceProvider function 2024-06-05 09:24:19 +03:00
Jan Rundt 48001b1f30 Merge branch 'master' into OOD-11 2024-06-05 09:17:42 +03:00
Jan Rundt 882d3c5846 OOD-11: lint fix 2024-06-05 09:07:59 +03:00
Jan Rundt 55f669a86d OOD-11: code cleanup, mostly 2024-06-05 09:05:00 +03:00
Jan Rundt c021c31157 Merge branch 'OOD-11' of github.com:UniversityOfHelsinkiCS/oodikone into OOD-11 2024-06-05 08:57:35 +03:00
Riku RauhalaandGitHub 7af4cd4668 Merge pull request #4526 from UniversityOfHelsinkiCS/OOD-9-hide-features-from-ui-dependening-service-provider
OOD-9: hide features from UI dependening service provider
2024-06-05 08:55:52 +03:00
Jan RundtandGitHub 69918b1728 Merge branch 'master' into OOD-11 2024-06-05 08:52:20 +03:00
Jan Rundt 35c36cffc6 OOD-11: notification that user has been added 2024-06-05 08:47:17 +03:00
Jan Rundt 520436e32f OOD-11: added listening to fetching changes 2024-06-05 08:15:46 +03:00
Jan Rundt 6b187b8a60 OOD-11: new user section sync and fail logic 2024-06-04 23:30:28 +03:00
Riku Rauhala c8a93cbf57 Include JSX files in the coverage report 2024-06-04 21:06:41 +03:00
Jan Rundt b4da19e4e6 OOD-11: backend fix, front NewUserSection still not working correctly 2024-06-04 19:49:31 +03:00
Matti Räsänen 6132ea5f57 OOD-11: Changed useGetAllUsersQuery to useLazyGetAllUsersQuery. Moved UsersSearchList api call to parent component and passing users, isLoading and isError as props to child component 2024-06-04 16:08:59 +03:00
Matti Räsänen bebeae8fb6 OOD-11: Searching users from sisu and adding them to Users db 2024-06-04 15:23:51 +03:00
renovate[bot]andGitHub 933fbd1689 Update dependency husky to v9 2024-06-04 08:36:10 +00:00
renovate[bot]andGitHub c0165fb02d Update dependency eslint-plugin-cypress to v3 2024-06-04 08:35:57 +00:00
Riku Rauhala 3465051e6b Fix package.json 2024-06-04 11:30:04 +03:00
Riku Rauhala 09f78e4e38 Update the instrumenting logic 2024-06-04 11:25:27 +03:00
Riku Rauhala 795c00a258 Add initial setup for code coverage 2024-06-04 11:25:26 +03:00
Jan Rundt 9789693dce OOD-11: WIP frontend part 2024-06-04 10:36:41 +03:00
Matti Räsänen 93f95d040c OOD-9: Refactored defining columns 2024-06-04 09:00:02 +03:00
Matti Räsänen e1246113b3 Merge branch 'master' into OOD-9-hide-features-from-ui-dependening-service-provider 2024-06-04 08:43:48 +03:00
Riku RauhalaandGitHub f1a5627180 Merge pull request #4525 from UniversityOfHelsinkiCS/OOD-10
OOD-10: user access logic depends on service provider env variable
2024-06-04 08:04:35 +03:00
Riku RauhalaandGitHub 993d8fa7be Merge pull request #4514 from UniversityOfHelsinkiCS/renovate/all-minor-patch
Update all non-major dependencies
2024-06-03 17:54:00 +03:00
Jan Rundt 719d3ee2c6 OOD-11: oriProvider and endpoint for fetching person 2024-06-03 15:56:09 +03:00
Riku Rauhala 44f622f306 Move tietosuoja.md to docs folder 2024-06-03 15:30:58 +03:00
Riku Rauhala a1f8ed8554 Update documentation 2024-06-03 14:45:12 +03:00
Matti Räsänen ec57728e80 Merge branch 'OOD-10' into OOD-9-hide-features-from-ui-dependening-service-provider 2024-06-03 12:54:46 +03:00
Matti Räsänen 054ce51c5f OOD-9: Changed SERVICE_PROVIDER env variable value to Fd 2024-06-03 12:42:07 +03:00
Matti Räsänen ecf4933e79 Merge branch 'master' into OOD-10-hide-features-from-ui-dependening-service-provider 2024-06-03 12:40:23 +03:00
Tereshchenko Aleksandr 0d96f022d9 Only open renovate PRs for LTS Node versions 2024-06-03 12:11:03 +03:00
Jan Rundt 6044bc70cc OOD-10: eslint fixes 2024-06-03 10:25:35 +03:00
Jan RundtandGitHub af8cd065cc Merge branch 'master' into OOD-10 2024-06-03 10:04:17 +03:00
renovate[bot]andGitHub 67020d34ea Update all non-major dependencies 2024-06-01 18:06:04 +00:00
Riku Rauhala d6c1cb3f49 [Faculties] Basic information: Filter out commissioned programme students 2024-05-31 16:48:24 +03:00
Riku Rauhala 85c315ea6f Rename some kisakoodari variables 2024-05-31 16:48:24 +03:00
Riku Rauhala f0aaa6755c [Backend] Refactor faculty functions 2024-05-31 16:48:24 +03:00
Riku Rauhala 7010014c4e Rearrange some functions for consistency 2024-05-31 16:48:24 +03:00
Riku Rauhala 2c2fc92103 [Faculties] Simplify transferShortTitle logic 2024-05-31 16:48:24 +03:00
Riku Rauhala 37cf9d2591 Remove commented out console.log 2024-05-31 16:48:24 +03:00
Riku Rauhala 47c5ae215c [Faculties] Update message texts 2024-05-31 16:48:24 +03:00
Riku Rauhala 05db26dd93 Fix backend/updater import order
The rule previously did not properly take into account the hierarchy
2024-05-31 16:48:24 +03:00
Jan RundtandGitHub a765cf0a9f Merge branch 'master' into OOD-10 2024-05-31 14:09:38 +03:00
Matti Räsänen 609a7f0be1 Merge branch 'master' into OOD-9-hide-features-from-ui-dependening-service-provider 2024-05-31 08:48:46 +03:00
Matti Räsänen fab749e3bd OOD-9: Added env variable SERVICE_PROVIDER as const serviceProvider to conf. Created function which will check is serviceProvider default (Toska) and taken that into use in few components. 2024-05-31 08:25:51 +03:00
Jan Rundt d6031a84ae OOD-10: mocked user implementation 2024-05-30 23:45:17 +03:00
renovate[bot]andGitHub aaeb577ffd Update dependency highcharts to v11 2024-05-30 15:01:07 +00:00
Jan Rundt bb1b1e6673 OOD-10: user access logic depending on service provider 2024-05-30 17:57:53 +03:00
Valtteri Kantanen 9433eb2abb Fix fetching students in user's study guidance groups 2024-05-30 15:33:10 +03:00
Valtteri KantanenandGitHub fa4b78720d Merge pull request #4516 from UniversityOfHelsinkiCS/OOD-2-fd-local-dev-enviroment
Created own docker compose file for funidata to run local dev enviroment
2024-05-30 14:45:02 +03:00
Matti Räsänen 1a833a627b OOD-2: Created own docker compose file for funidata to run local dev enviroment 2024-05-30 14:37:13 +03:00
Valtteri Kantanen 2b8ded490d Update Node.js to version 20 in all Dockerfiles 2024-05-30 14:06:29 +03:00
Valtteri KantanenandGitHub 10d1fefc07 Merge pull request #4513 from UniversityOfHelsinkiCS/renovate/node-20.x
Update Node.js to v20
2024-05-30 14:04:06 +03:00
renovate[bot]andGitHub fc0e4b51d6 Update Node.js to v20 2024-05-30 10:48:42 +00:00
Valtteri KantanenandGitHub 8eb75e476d Merge pull request #4511 from UniversityOfHelsinkiCS/renovate/npm-sequelize-vulnerability
Update dependency sequelize to v6 [SECURITY]
2024-05-30 13:23:50 +03:00
renovate[bot]andGitHub 4e3119dd9d Update dependency sequelize to v6 [SECURITY] 2024-05-30 10:09:31 +00:00
Tereshchenko Aleksandr aff75fbd7d Add renovate.json 2024-05-30 13:08:03 +03:00
Valtteri Kantanen f568255119 Revert "Use programmes instead of element details"
This reverts commit a5f7cd297c.
2024-05-30 12:37:38 +03:00
Valtteri Kantanen 283f390e70 Revert "[Faculties] Remove hard-coded faculty codes"
This reverts commit 84d331322a.
2024-05-30 11:43:01 +03:00
Valtteri Kantanen 03f838c5d2 [Study programme overview] Fix tests 2024-05-30 11:42:12 +03:00
Valtteri Kantanen 2bb8dfdde2 Fix ESLint error 2024-05-30 10:43:43 +03:00
Valtteri Kantanen 2d5be46161 [Class statistics] Update infotexts and simplify QueryCard 2024-05-30 10:39:10 +03:00
Valtteri Kantanen 396584b5d7 [Filters] Simplify styles on filter cards 2024-05-30 10:39:10 +03:00
Valtteri Kantanen 0f5bfd3466 [Filters] Make tag filter work with both include and exclude 2024-05-30 10:39:10 +03:00
Valtteri Kantanen c963261ee3 [Class statistics] Fix credits earned filter 2024-05-30 10:39:10 +03:00
Valtteri Kantanen 2a37467d0c [Class statistics] Only include tags from programme being observed 2024-05-30 10:39:10 +03:00
Valtteri Kantanen b20abbbf93 [Class statistics] Fix tag not being taken into account 2024-05-30 10:39:10 +03:00
Valtteri Kantanen a30b0655b9 [Class statistics] Show user if the deletion or creation of the tag was successful 2024-05-30 10:39:10 +03:00
Valtteri Kantanen 84d331322a [Faculties] Remove hard-coded faculty codes 2024-05-30 10:39:10 +03:00
Valtteri Kantanen 28c360d708 [Backend] Specify shared parts of API routes in routes.js 2024-05-30 10:39:10 +03:00
Valtteri Kantanen a5f7cd297c Use programmes instead of element details 2024-05-30 10:39:10 +03:00
Riku Rauhala 19906c5725 [Faculties] Write tests for file downloads 2024-05-30 09:12:56 +03:00
Riku Rauhala b948b4183a Ignore Cypress output directories 2024-05-30 08:43:41 +03:00
Riku Rauhala 5ffce68742 [Faculties] Basic information: Fix credits produced Excel export 2024-05-29 22:09:30 +03:00
Riku Rauhala 6a2bf5c108 [Faculties] Rename y to median 2024-05-29 15:49:57 +03:00
Riku Rauhala 83ef6f5760 [Faculties] Graduation times: Include median study times in Excel exports 2024-05-28 18:08:44 +03:00
Valtteri Kantanen 59de371d9a [Guidance groups] Add info about the Close to graduation feature 2024-05-28 17:42:37 +03:00
Valtteri Kantanen 362250868d [Class statistics] Remove code that is no longer used 2024-05-28 17:41:40 +03:00
Valtteri Kantanen 846d4b9ec7 [Sortable table] Remove check for headerRowData type: it's no longer a function 2024-05-28 17:39:34 +03:00
Valtteri Kantanen 6d8f4e0992 Remove unused CSS files 2024-05-28 17:38:03 +03:00
Valtteri Kantanen b41bfbd47e [Close to graduation] Allow user see students in their study guidance groups (#4503) 2024-05-28 17:22:32 +03:00
Riku Rauhala d774d5f073 [Faculties] Graduation times: set the year label based on grouping 2024-05-28 15:28:56 +03:00
Valtteri Kantanen 6259cfface [Class statistics] Fix automatic curriculum selection 2024-05-28 14:17:17 +03:00
Riku Rauhala 7cd101bb57 [Faculties] Add support for exporting in the Graduation Times tab 2024-05-28 14:01:59 +03:00
Riku Rauhala 329bd4696a [Updater] Sort model imports 2024-05-28 14:01:19 +03:00
Valtteri Kantanen 750a12e14b Remove unused backend route 2024-05-28 13:26:51 +03:00
Valtteri Kantanen f46a8fee5b [Teachers] Add provider code as a description 2024-05-28 13:25:55 +03:00
Valtteri Kantanen 0d8f51bc4f [Course statistics] Fix redux error and simplify the component 2024-05-28 13:25:34 +03:00
Valtteri Kantanen d3c01133b7 [Class statistics] Obfuscate some new fields 2024-05-28 13:24:41 +03:00
Valtteri Kantanen abb7d2211f [Class statistics] Allow to get course information if the student numbers are encrypted 2024-05-28 13:23:52 +03:00
Valtteri Kantanen dd7088c332 Add userId back 2024-05-27 14:44:44 +03:00
Riku RauhalaandGitHub 27bbfc6519 Merge pull request #4501 from UniversityOfHelsinkiCS/backend-imports
[Backend, Updater] Update and enforce a consistent import order
2024-05-27 11:00:45 +03:00
Riku Rauhala c1433392d4 [Backend, Updater] Update and enforce a consistent import order 2024-05-27 10:29:54 +03:00
Riku Rauhala f7131d361c [Class statistics] Fix broken access rights 2024-05-24 15:39:37 +03:00
Riku Rauhala 5840889fa9 Rename functions for consistency 2024-05-24 15:39:37 +03:00
Valtteri Kantanen 887b57fca7 Fix setting language 2024-05-24 15:21:43 +03:00
Valtteri Kantanen c496912d88 [Users] Remove sessions table from user-db 2024-05-24 14:53:17 +03:00
Valtteri Kantanen 442a58c74a [Users] Remove unnecessary tables and columns from user-db 2024-05-24 14:13:13 +03:00
Valtteri Kantanen ac1632c1e1 [Close to graduation] Add master's students 2024-05-24 11:49:07 +03:00
Valtteri Kantanen 25dc072b2e [Users] Take userService changes into account in the frontend 2024-05-24 10:01:04 +03:00
Valtteri Kantanen 46b575ae6d Refactor userService completely 2024-05-24 09:59:16 +03:00
Valtteri Kantanen 24fafbe4ff Upgrade lru-cache version 2024-05-24 09:58:13 +03:00
Valtteri Kantanen 18f6d6157c Add roles and programmeRights to users table 2024-05-24 09:57:54 +03:00
Riku Rauhala 3c27f19ea1 Format curriculum periods in the frontend 2024-05-23 17:04:34 +03:00
Riku Rauhala ad7c36f235 [Users] Update email button text 2024-05-23 14:51:39 +03:00
Riku Rauhala 6caebdab25 [Class statistics] Fix curriculum year ranges 2024-05-22 20:23:16 +03:00
Riku Rauhala 58423df517 Refactor CourseTab
Rename variables and improve readability
2024-05-22 15:52:29 +03:00
Riku Rauhala a547382f1c Use consistent spelling for email
All other instances use the spelling email instead of e-mail
2024-05-22 09:40:03 +03:00
Valtteri Kantanen bf178fb086 [Class statistics] Fix small percentages not showing in credit gain stats 2024-05-21 18:33:57 +03:00
Valtteri Kantanen fc023f09cb [Class statistics] Add median to credit gain stats 2024-05-21 18:32:28 +03:00
Valtteri Kantanen 3fe9683c98 [Class statistics] Fix filtering by admission type 2024-05-21 18:31:28 +03:00
Riku Rauhala 8d20225a57 [Class statistics] Update pagination icons 2024-05-21 17:27:14 +03:00
Riku Rauhala b83c90dca1 [Class statistics] Fix ghost border 2024-05-21 11:49:39 +03:00
Riku Rauhala 47de8e89c3 Add a default value for the search history header 2024-05-21 09:14:05 +03:00
Riku Rauhala 64606c2a98 Refactor search history 2024-05-20 20:00:51 +03:00
Valtteri Kantanen b5e913d85e Fix tests 2024-05-20 19:50:43 +03:00
Valtteri Kantanen 8e5dcb3e78 Add retries to flaky filters tests 2024-05-20 19:39:26 +03:00
Valtteri Kantanen ebd03acff0 [Courses tab] Fix table flowing over its borders 2024-05-20 19:35:56 +03:00
Valtteri Kantanen 0fe06bfd12 [Course statistics] Exclude selected primary groups from comparison group options 2024-05-20 19:15:49 +03:00
Valtteri Kantanen 3f564ab66a [Course statistics] Fix filtering statistics by study programme 2024-05-20 19:15:49 +03:00
Valtteri Kantanen 9e6349739a [Course population] Fix visibility for users with full Sisu access 2024-05-20 19:15:49 +03:00
Valtteri Kantanen d1936c6358 [Close to graduation] Only show current study tracks 2024-05-20 19:15:49 +03:00
Riku Rauhala a075df412c Update some titles for consistency 2024-05-20 17:51:59 +03:00
Valtteri Kantanen b53d84f706 [Updater] Increase Sequelize acquire timeout closer to the one in the backend 2024-05-20 10:52:12 +03:00
Valtteri Kantanen 0312174e40 Add a button for refreshing the close to graduation data 2024-05-20 10:51:14 +03:00
Valtteri Kantanen 442ced9124 Add logging to see how long a big db query takes to finish 2024-05-17 15:06:20 +03:00
Valtteri Kantanen ea9345d82c [Students] Fix tests 2024-05-17 10:15:11 +03:00
Valtteri Kantanen 132bf930fb Upgrade React 16 to React 18 2024-05-17 10:04:12 +03:00
Valtteri Kantanen 980fbef339 [Students] Fix calculation of average grades 2024-05-16 23:15:56 +03:00
Valtteri Kantanen c68e9abfd4 [General tab] Fix page crashing if no correct studyright is found 2024-05-16 17:58:50 +03:00
Valtteri Kantanen 530435a069 [Class statistics] Fix filtering with credit distribution development 2024-05-16 17:09:32 +03:00
Valtteri Kantanen 8cbd4fd957 [Study guidance groups] Fix tests 2024-05-16 17:01:50 +03:00
Valtteri Kantanen 3152e5a76d [Close to graduation] Fix column resizing over and over again 2024-05-16 16:39:58 +03:00
Valtteri Kantanen 0c8510e4fd [Users] Display a message if a user has full access to Sisu 2024-05-13 18:04:41 +03:00
Valtteri Kantanen 9f4eb5947a [Faculties] Fix sorting faculty array 2024-05-13 17:27:38 +03:00
Valtteri Kantanen 52760ab18f [Course statistics] Prevent page from crashing if no study programme is found 2024-05-13 17:23:21 +03:00
Valtteri Kantanen 977a24749b [Close to graduation] Add helptexts 2024-05-13 15:25:20 +03:00
Valtteri Kantanen 9c12a53104 [Close to graduation] Add curriculum period 2024-05-13 14:12:15 +03:00
Valtteri Kantanen 23df779857 [Class statistics] Remove animation from credit distribution development 2024-05-13 12:53:43 +03:00
Valtteri Kantanen 9db047697f [Students] Fix grade graph by semester 2024-05-13 12:52:35 +03:00
Valtteri Kantanen 9863ca9072 [Students] Fix eternal loading state if request fails 2024-05-13 12:52:03 +03:00
Valtteri Kantanen 8aa7fcfa9b [Updater] Improve error logging to help figure out why study plans might not update 2024-05-10 15:49:36 +03:00
Valtteri Kantanen b82e665b23 [Class statistics] Reduce the number of re-renders 2024-05-10 14:25:50 +03:00
Valtteri Kantanen eb99e4daaa [Sortable table] Optimize re-renders 2024-05-10 14:25:50 +03:00
Riku Rauhala 0ffe7330fa Retry running the 'Reset All Filters' test twice 2024-05-10 14:10:00 +03:00
Riku Rauhala a5902287a9 Create a separate component for the old programmes filter toggle 2024-05-10 14:07:44 +03:00
Riku Rauhala 82ed3ee9bb [Sortable table] Fix the help text icon
The help text icon now only shows up when the help text is set. The placeholder icon has been removed and the actual icon button is always visible instead
2024-05-10 13:45:30 +03:00
Riku Rauhala f4f9e3ae72 [Open uni population] Refactor results 2024-05-10 11:37:23 +03:00
Riku Rauhala 20c68c8902 [Study programmes] Refactor selector into smaller components 2024-05-10 11:37:02 +03:00
Riku Rauhala eafa79174f [Study programmes] Filter out old programmes by default 2024-05-10 10:09:27 +03:00
Riku Rauhala 4e9ae474b9 Fix Faculty statistics tests 2024-05-08 15:17:58 +03:00
Riku Rauhala fa0e0de8c6 [Faculties] Update the style of the Faculties selection 2024-05-08 14:25:46 +03:00
Riku Rauhala f1e3527ae1 [Study programmes] Add a helper text to the Pin column 2024-05-08 14:06:30 +03:00
Riku Rauhala a25f18f953 [Study programmes] Fix loading 2024-05-08 13:45:19 +03:00
Riku Rauhala 0800a5f4cb Remove common/query 2024-05-08 10:40:43 +03:00
Riku Rauhala 6374a99d0d Change the pin icon from boomark to pin
The feature is pinning, not bookmarking
2024-05-07 12:21:52 +03:00
Riku Rauhala 1ea432df46 [Class statistics] Update info button text 2024-05-07 12:11:49 +03:00
Riku Rauhala a31734c1d4 [Study programme search] Display a pin icon for pinned programmes 2024-05-07 11:25:43 +03:00
Riku Rauhala 2f83b41ebb [Study programme search] Sort pinned programmes first 2024-05-07 11:01:15 +03:00
Riku Rauhala 4506005e58 Add the actual comparator function... 2024-05-07 10:51:58 +03:00
Riku Rauhala bbae08286a Move pinned first comparator to common for reuse 2024-05-07 10:49:54 +03:00
Valtteri Kantanen 5bc77f9298 [Users] Only copy displayed users' email addresses to the clipboard 2024-05-06 16:54:11 +03:00
Valtteri Kantanen 77f8d26cb7 [Sortable table] Change handleRowCountChange prop to handleDisplayedDataChange 2024-05-06 16:54:11 +03:00
Riku Rauhala 8fcf552301 [Study programmes] Sort pinned programmes first 2024-05-06 15:54:10 +03:00
Riku Rauhala 74f390e017 Change title from Study programme to Study programmes 2024-05-06 15:34:37 +03:00
Riku Rauhala d0f68296bf [Backend] Respond with appropriate status codes 2024-05-06 14:36:24 +03:00
Riku Rauhala 613de498bb [Backend] Prefix unused req variables
For consistency, all unused req variables inside routers should be prefixed with an underscore
2024-05-06 14:28:39 +03:00
Riku Rauhala 7560d6ce5f [Study programmes] Add support for pinning programmes 2024-05-06 14:19:43 +03:00
Valtteri Kantanen e6262838a6 [Updater] Filter out misregistrations after all 2024-05-06 12:49:42 +03:00
Valtteri Kantanen 6178d3ddaa [Tags] Invalidate students in cache after creating or deleting new tags 2024-05-06 12:38:25 +03:00
Valtteri Kantanen e4394779d0 [Updater] Simplify a couple of functions 2024-05-06 10:38:58 +03:00
Valtteri Kantanen a3b2ed8941 [Study programme overview] Fix adding new student tags 2024-05-06 10:38:58 +03:00
Valtteri Kantanen 345c954e88 [Students] Use RTK Query instead of Redux 2024-05-06 10:38:58 +03:00
Valtteri Kantanen 9e91e447bc Use specific hook instead of useSelector 2024-05-06 10:38:58 +03:00
Valtteri Kantanen f937902279 [Course statistics] Fix filtering by study programme 2024-05-06 10:38:58 +03:00
Riku Rauhala abfd629e05 [Faculties] Improve the filter 2024-05-06 10:28:30 +03:00
Valtteri Kantanen 39fedc6a99 [Sortable table] Fix documentation 2024-05-03 16:07:51 +03:00
Valtteri Kantanen 8f170586d3 [General tab] Show only other programmes on class statistics 2024-05-03 16:07:18 +03:00
Valtteri Kantanen b4345b5d51 [General tab] Fix semester enrollments in Excel 2024-05-03 16:06:04 +03:00
Riku Rauhala 97819db858 Improve the study programme filter 2024-05-03 15:48:37 +03:00
Riku Rauhala 4959d5bf51 Refactor study programme selector 2024-05-03 15:06:22 +03:00
Riku Rauhala 3cbdae8046 [kone-db] Add table study_programme_pins 2024-05-03 12:23:38 +03:00
Riku Rauhala 6c86bf9b0e [Class statistics] Fix study track selection 2024-05-02 15:17:44 +03:00
Valtteri Kantanen b42f87351f [General tab] Fix page crashing if there are no valid first and last semesters 2024-04-30 19:28:35 +03:00
Valtteri Kantanen 98b6daed03 [Close to graduation] Enable for users with full access to Sisu 2024-04-30 19:13:28 +03:00
Valtteri Kantanen 47a5015014 [Users] Fetch sisu access from Jami with other roles 2024-04-30 19:13:28 +03:00
Valtteri Kantanen a80afd701c Fix needed roles for one backend endpoint 2024-04-30 19:13:28 +03:00
Valtteri Kantanen 3ccbf35d6c [Study guidance groups] Fix tests 2024-04-30 19:13:28 +03:00
Riku Rauhala 2f50e12253 [General tab] Change semester export range logic 2024-04-30 18:01:04 +03:00
Riku Rauhala b62ed4092d [General tab] Export all semesters from start year of programme 2024-04-30 16:35:46 +03:00
Riku Rauhala 4dd9da1b37 Acually for real fix e2e tests 2024-04-30 10:42:54 +03:00
Riku Rauhala 3632ad5ea6 Acually fix e2e tests 2024-04-30 10:24:31 +03:00
Riku Rauhala 8b600fe9f1 Fix e2e tests 2024-04-30 10:15:00 +03:00
Riku Rauhala ca83972ba6 [General tab] Export each semester enrollment status in separate columns 2024-04-30 09:05:16 +03:00
Valtteri Kantanen 84e8af82b0 [Users] Display fullSisuAccess label in orange 2024-04-29 17:37:40 +03:00
Valtteri Kantanen d74338eca1 [Users] Fix mocking not working 2024-04-29 15:57:17 +03:00
Riku Rauhala 2ef05730cf [Course tab] Fix weird table title 2024-04-29 13:38:24 +03:00
Valtteri Kantanen ad93fde755 [Population programmes] Replace Redux with RTK Query 2024-04-29 12:33:10 +03:00
Valtteri Kantanen e5fc45a560 [Population search form] Hide error message about missing rights if programmes are loading 2024-04-29 10:30:56 +03:00
Valtteri Kantanen c0f690d357 [Class statistics] Remove unused CSS 2024-04-29 10:14:28 +03:00
Valtteri Kantanen f64b688b0d [Class statistics] Make code more concise 2024-04-29 10:04:55 +03:00
Valtteri Kantanen 252f4a8592 [Class statistics] Fix resetting credit filter 2024-04-29 10:02:06 +03:00
Valtteri Kantanen 9e9bd08974 [Class statistics] Remove unused prop 2024-04-29 09:58:41 +03:00
Valtteri Kantanen ce7a877d74 [Front page] Fix toska.dev link width 2024-04-29 09:56:47 +03:00
Valtteri Kantanen 6ec734b188 Remove old pictures 2024-04-29 09:55:45 +03:00
Valtteri Kantanen 321ac00291 [Tags] Simplify logic of tags 2024-04-26 16:36:18 +03:00
Valtteri Kantanen 6a6a75bdb6 [Tags] Fix tests 2024-04-26 16:20:39 +03:00
Valtteri Kantanen 0b768652af [Tags] Simplify handling of tags 2024-04-26 15:24:38 +03:00
Valtteri Kantanen a49e526219 [Population statistics] Simplify fetching of tags and study programmes 2024-04-26 13:16:35 +03:00
Valtteri Kantanen 74ca5ec6f9 Allow full access to student data in Oodikone for users who have the same rights in Sisu (#4441) 2024-04-26 10:07:01 +03:00
Valtteri Kantanen c74c32d2ea Add new npm scripts to install node_modules more easily 2024-04-26 09:52:45 +03:00
Valtteri Kantanen 07aa20074e Update more dependencies 2024-04-25 18:33:53 +03:00
Valtteri Kantanen 3f0ff8a22a [Class statistics] Remove a couple of ESLint errors 2024-04-25 18:04:43 +03:00
Valtteri Kantanen fe821dadeb [Faculties] Remove unneeded expression 2024-04-25 17:41:56 +03:00
Valtteri Kantanen 77e63d5493 [Completed courses] Fix sorting enrollments by date 2024-04-25 17:20:51 +03:00
Valtteri Kantanen cddce1b5e7 Update minor versions of dependencies 2024-04-25 12:09:40 +03:00
Valtteri Kantanen 85decaa997 Allow use of for..of statements 2024-04-24 15:11:44 +03:00
Valtteri Kantanen 1dcf2fe389 [General tab] Simplify logic for checking if selected students have studytracks 2024-04-24 14:35:59 +03:00
Valtteri Kantanen f3deb61ebf [Class statistics] Don't fetch curriculum info if there are no selected years 2024-04-24 14:35:07 +03:00
Valtteri Kantanen 0891651b69 [Updater] Remove duplicate code 2024-04-24 13:30:05 +03:00
Valtteri Kantanen dbf2666f03 [Students] Prevent page from crashing if correct transfer is not found 2024-04-24 13:28:16 +03:00
Valtteri Kantanen 65bc30bae2 [Class statistics] Optimize backend requests 2024-04-24 13:11:47 +03:00
Riku Rauhala 21fb304166 [General tab] Fix the study track column not showing 2024-04-22 15:44:29 +03:00
Riku Rauhala 84294ae725 [Population details] Fix broken date 2024-04-22 14:03:00 +03:00
Riku Rauhala cec08667bb Acually fix e2e tests 2024-04-19 13:46:44 +03:00
Riku Rauhala 2953a3247b Fix e2e tests 2024-04-19 13:39:34 +03:00
Riku Rauhala 76a6d1fd6f Rename curriculum version to curriculum period 2024-04-19 13:31:38 +03:00
Riku Rauhala 53fc49e8c3 Create curriculum version filter 2024-04-19 13:06:56 +03:00
Valtteri Kantanen b17d77ba6d Fetch Sisu access from Jami 2024-04-19 10:40:03 +03:00
Riku Rauhala 7a6cc4bdb3 [Population] Add gender column 2024-04-19 09:06:14 +03:00
Valtteri Kantanen fe6204ddd6 Fix time formatting 2024-04-16 16:38:19 +03:00
Riku Rauhala 30af49a0b7 [Class statistics] Update info box 2024-04-16 16:09:08 +03:00
Riku Rauhala d8f5873eeb Acually for real fix e2e tests 2024-04-16 16:04:00 +03:00
Riku Rauhala 15d0618279 Fix population statistics tests 2024-04-16 15:52:12 +03:00
Riku Rauhala c212263149 [Class statistics] Move the curriculum version column 2024-04-16 15:49:08 +03:00
Riku Rauhala 5658f096c7 [Class statistics] Update curriculum version end year 2024-04-16 15:43:17 +03:00
Riku Rauhala 156945bd4e Acually fix e2e tests 2024-04-16 15:42:33 +03:00
Riku Rauhala ecda8d8baf Fix e2e tests 2024-04-16 15:34:58 +03:00
Riku Rauhala 3e9541d675 [Population] Add curriculum version to the General tab 2024-04-16 15:23:25 +03:00
Riku Rauhala 66a1d4915a [Backend] Return curriculum version 2024-04-16 15:23:01 +03:00
Valtteri Kantanen b1cc1cbb77 [Class statistics] Fix info message visibility 2024-04-16 12:59:36 +03:00
Riku Rauhala 5005fb4c13 [Backend] Return curriculum_period_id 2024-04-16 12:19:50 +03:00
Valtteri Kantanen dcd994ada9 [Completed courses search] Make search case-insensitive 2024-04-16 12:19:30 +03:00
Valtteri Kantanen cb74c7989f [Class statistics] Fix info message visibility 2024-04-16 12:00:42 +03:00
Riku Rauhala 081de75687 [Updater] Add curriculum_period_id to studyplan 2024-04-16 11:32:10 +03:00
Valtteri Kantanen 5c36b858f4 [Class statistics] Display an info message if class size is 0 2024-04-16 10:36:40 +03:00
Valtteri Kantanen f5f2e7ce0a [Class statistics] Add some advanced settings back because they seem to be working now 2024-04-16 10:35:37 +03:00
Valtteri Kantanen 2ceb1525a6 Include medicine, dentistry and veterinary specialization training in student's programmes 2024-04-16 10:19:24 +03:00
Valtteri Kantanen 2bd4624b80 [Updater] Fix logic for checking whether a study right is active or not 2024-04-16 10:15:20 +03:00
Riku Rauhala 3578c04a46 [Class statistics] Add margin 2024-04-16 09:36:53 +03:00
Riku Rauhala 3e77674213 [Study guidance groups] Add missing info box 2024-04-15 14:22:22 +03:00
Riku Rauhala 168dc43634 [Study guidance groups] Remove custom study start year 2024-04-15 13:56:17 +03:00
Valtteri Kantanen b0f7495e5e [Close to graduation] Make pagination icons clearer 2024-04-15 13:20:38 +03:00
Valtteri Kantanen 1e09cc7c1b [Study programme overview] Fix users not being able to modify visible degree courses 2024-04-15 11:56:00 +03:00
Valtteri Kantanen 083f387e9b [Updater] Fix error when inserting new attainments 2024-04-15 10:59:01 +03:00
Riku Rauhala 5b8e971daf [Study guidance groups] Fix the credit date filter 2024-04-12 20:53:42 +03:00
Riku Rauhala a41624fbd5 Update labels for consistency 2024-04-12 14:07:50 +03:00
Valtteri Kantanen 6b3055e57d [Students] Fix highlighting of courses after selecting a study programme 2024-04-10 16:11:31 +03:00
Valtteri Kantanen 954cb157ab [Close to graduation] Add a toggle for showing semester enrollments 2024-04-10 14:47:50 +03:00
Valtteri Kantanen 16db5d2711 [Close to graduation] Rearrange columns 2024-04-10 14:29:43 +03:00
Valtteri Kantanen 7a13b451c8 [Close to graduation] Hide pagination if all students fit to one page 2024-04-10 14:27:03 +03:00
Valtteri Kantanen ddcd061103 [GHA workflow] Don't print progress info when pulling images 2024-04-10 14:24:34 +03:00
Valtteri Kantanen 8e0103d517 [Sortable table] Fix table not rendering 2024-04-09 18:17:27 +03:00
Valtteri Kantanen edb0515988 [Close to graduation] Add semester enrollment info 2024-04-09 18:06:18 +03:00
Valtteri Kantanen 84cdc47358 [Study guidance groups] Fix e2e test for general tab of the students table 2024-04-09 16:07:44 +03:00
Riku Rauhala 3281dac16f [Study guidance groups] Add missing columns
When studyprogramme and year are selected, the General tab now matches what is shown in the Class statistics page
2024-04-09 15:35:05 +03:00
Riku Rauhala 1b06d8b6e3 Acually for real this time fix e2e tests 2024-04-09 13:42:10 +03:00
Riku Rauhala 822302005b Acually for real fix e2e tests 2024-04-09 13:32:25 +03:00
Riku Rauhala f72d3a99f3 Acually fix e2e tests 2024-04-09 13:23:36 +03:00
Riku Rauhala 0253707747 Fix e2e tests 2024-04-09 13:13:21 +03:00
Riku Rauhala a3bd88bcd3 Update legacy references to Oodi 2024-04-09 13:03:51 +03:00
Riku Rauhala 3987247e8f [Sortable table] Align numeric values to the right 2024-04-09 12:42:54 +03:00
Riku Rauhala 6333e1d880 [General tab] Simplify timestamps 2024-04-09 10:56:04 +03:00
Riku Rauhala 5b9ca5c5e6 [Course statistics] Include enrolled, no grade in the grade distribution chart 2024-04-09 10:33:37 +03:00
Valtteri Kantanen 3ccf18f383 [Close to graduation] Add latest attainment dates 2024-04-08 19:00:10 +03:00
Valtteri Kantanen 9bddf17899 [Close to graduation] Allow searching on faculty and programme dropdown menus 2024-04-08 17:21:24 +03:00
Valtteri Kantanen 3f6f2626ca [Sortable table] Default useFilteredDataOnExport to true 2024-04-08 17:20:53 +03:00
Riku Rauhala ef77d4b249 [Study guidance groups] Fix broken dates 2024-04-08 14:59:55 +03:00
Riku Rauhala 0a1d6cad5d [Study guidance groups] Fix broken dates
In Credit statistics -> Credits gained tab the dates were broken because the year parameter was handled incorrectly
2024-04-08 12:34:47 +03:00
Riku Rauhala 9ed757d8cb [Study guidance groups] Hide avg start age when programme is not selected
The study programme is used to calculate the average age at the start of studies. This calculation cannot be done if the programme is not selected and would lead to negative numbers with no meaning
2024-04-08 10:03:52 +03:00
Valtteri Kantanen a4d2d43a18 Replace docker-compose with docker compose in GHA workflow files 2024-04-03 16:22:28 +03:00
Valtteri Kantanen 5a4d37556c [Class statistics] Add citizenship filter 2024-04-03 16:13:18 +03:00
Valtteri Kantanen 29bfa84c2a [Class statistics] Add a citizenship field to General tab 2024-04-03 14:58:41 +03:00
Valtteri Kantanen fbabd4ff35 [Close to graduation] Add a programme filter 2024-04-02 17:23:53 +03:00
Valtteri Kantanen bde839dbd9 [Close to graduation] Add study track info 2024-04-02 17:22:58 +03:00
Valtteri Kantanen 31d0912e1e [Sortable table] Add possibility to use filtered data in exported files and pass the number of filtered rows to the parent 2024-04-02 15:59:55 +03:00
Valtteri Kantanen 5da695f2c0 Reformat message about updated privileges 2024-04-02 14:41:52 +03:00
Valtteri Kantanen 57f334bf07 [Students close to graduation] Add phone number and email to Excel file 2024-04-02 14:31:07 +03:00
Valtteri Kantanen 91568510fa [Students close to graduation] Update feature name 2024-04-02 14:31:07 +03:00
Riku Rauhala 04408fb3f2 Remove unused exported declaration 2024-04-02 14:30:16 +03:00
Riku Rauhala 27f22ded2e [Study guidance groups] Fix the page crashing with a non-existent id 2024-04-02 14:21:11 +03:00
Riku Rauhala 2ac00b5fb1 [Access denied] Remove credits 2024-04-02 13:50:11 +03:00
Riku Rauhala f1c8f2ce43 [Population details] Fix average age for grouped ages 2024-04-02 10:30:11 +03:00
Riku Rauhala ff7721f154 Rearrange imports 2024-04-02 09:43:23 +03:00
Riku Rauhala 0b4fd527dd Update imports 2024-04-02 09:16:27 +03:00
Valtteri Kantanen dbd9180da5 [Sortable table] Fix sort order (#4459) 2024-03-27 17:18:46 +02:00
Valtteri Kantanen c03abae5d4 [Close to graduation] Calculate new data daily and cache it in Redis 2024-03-27 14:34:49 +02:00
Riku Rauhala 811dc37ef9 Disable Highcharts credits for the remaining charts 2024-03-26 21:55:16 +02:00
Riku Rauhala acb346c77a [Student statistics] Remove unnecessary padding 2024-03-26 21:41:49 +02:00
Riku Rauhala 98b4cba041 [Student statistics] Fix a typo and tweak styles 2024-03-26 21:22:08 +02:00
Valtteri Kantanen c0beb94d60 Add possibility to filter by faculty on close to graduation report 2024-03-26 20:36:41 +02:00
Valtteri Kantanen c0de109c0f Add thesis status to close to graduation report 2024-03-26 20:06:02 +02:00
Riku Rauhala c0c6a6a10c [Student statistics] Align the Credits column to the right 2024-03-26 19:59:33 +02:00
Riku Rauhala 033d5bd86f [Student details] Round grade graph mean values to 2 decimals 2024-03-26 19:33:53 +02:00
Riku Rauhala c8ad866635 [Student details] Fix style issues 2024-03-26 18:03:40 +02:00
Valtteri Kantanen c4f9dbdb27 Add first implementation for report of close to graduation students 2024-03-26 17:33:49 +02:00
Riku RauhalaandGitHub 0507111117 Merge pull request #4457 from UniversityOfHelsinkiCS/study-guidance-groups
[Study guidance groups] Add support for removing study programme or starting year
2024-03-26 16:24:36 +02:00
Riku Rauhala 132b454937 Fix e2e tests 2024-03-26 16:16:22 +02:00
Riku Rauhala 3a7842765a [Study guidance groups] Add support for removing study programme or starting year 2024-03-26 16:04:42 +02:00
Riku Rauhala 9d92571770 [Study guidance groups] Fix alignments 2024-03-26 12:15:10 +02:00
Riku Rauhala d3340a80b1 Random bullshit, go 2024-03-26 11:43:15 +02:00
Riku Rauhala cc0ec6fdd9 [Study guidance groups] Change the trash icon to a cancel icon for the cancel button 2024-03-26 11:27:08 +02:00
Valtteri Kantanen bd85a6a5ba [Updater] Don't filter out misregistrations from attainments (#4453) 2024-03-25 17:26:18 +02:00
Riku Rauhala a52063ac37 Use the same case in every title in the application 2024-03-25 15:13:15 +02:00
Riku Rauhala facdb85cec Rename variables 2024-03-25 12:22:04 +02:00
Riku Rauhala 05673e269d [Study programme] Fix colours getting mixed up
When excluding special studyrights, the colours would get mixed up. Sorting the graphStats by name returns them in the same order so the colours don't randomly change when toggling
2024-03-22 13:50:45 +02:00
Riku Rauhala e479738a27 [Study programme] Flip the specialGroups condition 2024-03-22 13:06:45 +02:00
Valtteri Kantanen 692fab5d75 Add retries to a flaky test 2024-03-22 12:49:26 +02:00
Riku RauhalaandValtteri Kantanen d93b52f600 [Study programme] Fix credits produced when special studyrights are exluded
Co-authored-by: Valtteri Kantanen <valtteri.kantanen@iki.fi>
2024-03-22 12:38:49 +02:00
Riku Rauhala efbf24c003 [Study programme] Fix the special studyright toggle 2024-03-22 11:49:27 +02:00
Riku Rauhala 987c8b3a97 Remove unused props 2024-03-22 09:47:16 +02:00
Valtteri Kantanen 57cad29520 [Updater] Fix study plans not including all the courses in student's study plan (#4390) 2024-03-20 18:36:54 +02:00
Valtteri KantanenandGitHub 268fc7c8e9 Merge pull request #4451 from UniversityOfHelsinkiCS/firefox-fix
[Class statistics] Fix broken dates on Firefox
2024-03-20 16:40:25 +02:00
Valtteri Kantanen d63e69a950 Rename two "student" variables to "studentNumber" 2024-03-20 16:26:56 +02:00
Valtteri Kantanen 29218cd9d2 [Class statistics] Fix logic for finding the correct studyright element 2024-03-20 16:22:37 +02:00
Riku Rauhala f81cbe1d4f [Class statistics] Fix broken dates on Firefox 2024-03-20 12:06:16 +02:00
Riku Rauhala 852c91219c [Population students] Rename variables 2024-03-20 11:35:55 +02:00
Valtteri Kantanen a94dcd2a9d Use a function expression in the tooltipFormatter: this is necessary as the keyword this behaves differently in arrow functions 2024-03-19 17:06:18 +02:00
Riku Rauhala 874fdf83e1 Update imports 2024-03-19 13:59:36 +02:00
Riku Rauhala 5aefe58e46 Convert the remaining functions to arrow syntax 2024-03-19 13:39:34 +02:00
Riku Rauhala 9047e099dc Move a duplicate getAge function to common 2024-03-19 13:37:56 +02:00
Riku Rauhala ce03560ff8 Rename most 's' mystery variables
These variables had the following meanings: semester, series, status, student or studyright. Some variables are harder to decipher so they are left for now
2024-03-19 13:13:27 +02:00
Riku Rauhala 068458d4be [Student statistics] Update style 2024-03-19 12:25:54 +02:00
Valtteri Kantanen 68767a301e Fix CI/CD workflow for PRs 2024-03-19 12:14:16 +02:00
Riku Rauhala b443ead517 [Changelog] Add JSDoc to getDescription 2024-03-19 11:47:37 +02:00
Riku Rauhala b743e49ff1 [Changelog] Update logic for parsing the description
It shouldn't matter how the word 'internal' is spelled or included in the description. Now the internal section of the changelog begins at any line that contains the keyword 'internal'
2024-03-19 11:45:25 +02:00
Riku Rauhala 5548940ea4 Rename 'c' mystery variables
Give all 'c' variables more meaningful names. Depending on the context, 'c' could mean any of these things: child, code, column, course, credit, curriculum or studyright
2024-03-19 10:52:26 +02:00
Riku Rauhala 665e0ed6e4 Rename more kisakoodari variables 2024-03-18 15:27:18 +02:00
Riku Rauhala f7247a73ec Rename evt variables
Rename evt to event for consistency
2024-03-18 15:20:31 +02:00
Riku Rauhala c9e259a1ea Rename srE variables
Rename srE to element or studyrightElement depending on the context
2024-03-18 15:18:55 +02:00
Riku Rauhala 203ee46a7c Rename sr variables
Rename sr to studyright for consistency
2024-03-18 15:13:39 +02:00
Riku Rauhala afe70fdb67 Rename element relates variables
Rename el or elem to element for consistency
2024-03-18 15:06:45 +02:00
Riku Rauhala df831aeef7 Rename most 'e' variables
There were tons of kisakoodari tier variables named simply e with varying meanings: element, enrollment, error, event...
2024-03-18 14:27:56 +02:00
Riku Rauhala 0021c44c2c Rename idx -> index
In most cases the variable name index is used, replace the remaining cases of idx with index for consistency with the rest of the codebase
2024-03-18 12:51:42 +02:00
Riku Rauhala 4b4a671a70 Fix SortableTable key issue 2024-03-18 12:44:05 +02:00
Riku Rauhala 1aed2d2ff8 Sort eslint rules 2024-03-18 12:17:28 +02:00
Riku Rauhala 3a10c22b80 [Course statistics] Add missing bottom margin when the direction is toggled 2024-03-18 11:51:24 +02:00
Riku Rauhala 60851c88e5 [Course statistics] Update table header formatting 2024-03-18 11:44:36 +02:00
Riku Rauhala efdc2abbef [Study guidance groups] Add missing margin and center content 2024-03-18 10:31:16 +02:00
Riku Rauhala eeab572c5d Rename Study programme and Course statistics titles for consistency 2024-03-18 10:06:04 +02:00
Valtteri Kantanen 1a25f3aae6 Add GHA workflow for running tests on PRs 2024-03-15 20:51:19 +02:00
Riku Rauhala 40ea7c8752 [Study programme] Fix null text in some expanding some years 2024-03-15 19:53:52 +02:00
Riku Rauhala 7442513927 [Study programme] Fix broken population link 2024-03-15 19:53:52 +02:00
Riku Rauhala 67ee85dd41 Refactor StudytrackDataTable 2024-03-15 19:53:52 +02:00
Valtteri Kantanen 1f3ecb4952 [GHA workflow] Require successful linting before running tests for updater 2024-03-15 15:18:54 +02:00
Valtteri Kantanen 8c271d0fab [Updater] Lint files in GHA workflow 2024-03-15 15:04:31 +02:00
Valtteri Kantanen d678ac2a6a Combine CI/CD pipeline jobs for linting backend and frontend 2024-03-15 15:03:16 +02:00
Valtteri Kantanen 8ccd5cdae5 [Updater] Update logic for finding students whose studyplan to update to avoid circular dependency 2024-03-15 14:39:22 +02:00
Riku Rauhala 6f999fa203 Bump immer to 9.0.21 2024-03-15 12:04:19 +02:00
Valtteri Kantanen 5cbc827d1d [Updater] Split updateStudents into multiple files 2024-03-15 10:55:03 +02:00
Tereshchenko Aleksandr 4cdcd948f6 Add links to updater-scheduler and -worker READMEs to the root README 2024-03-15 09:21:03 +02:00
Arttu KangasandGitHub 9c4ab07fb8 Merge pull request #4442 from UniversityOfHelsinkiCS/updater-scheduler-readme
Add workflow overview to updater-scheduler's and updater-worker's READMEs
2024-03-14 19:31:10 +02:00
Arttu KangasandGitHub 5e86ff05f3 Add explanation of what purge is, typo fixes 2024-03-14 19:30:23 +02:00
Tereshchenko Aleksandr d017a23ab5 Add workflow overview to updater-worker's README 2024-03-14 16:08:14 +02:00
Valtteri Kantanen 250024d41d Fix ESLint errors for backend and updater 2024-03-14 15:51:33 +02:00
Tereshchenko Aleksandr 1420628f6f Add workflow overview to updater-scheduler's README 2024-03-14 14:11:30 +02:00
Valtteri Kantanen e1cc1f3ecc Move many ESLint rules to the root level 2024-03-12 18:51:11 +02:00
arttu 2d0d152fb7 [Updater] Fix resolving 'is_open' in credits, improve code 2024-03-12 18:27:42 +02:00
Valtteri Kantanen 2272890cb4 [Course statistics] Fix page crashing because of missing studyrights 2024-03-12 17:50:49 +02:00
Valtteri Kantanen ba8471df88 Remove the rest of absolute imports without '@' 2024-03-12 17:42:22 +02:00
arttu 575a580120 [OpenUni] Fix credits not showing 2024-03-12 17:35:42 +02:00
Valtteri Kantanen 0a07dedede [Course population] Improve logic for finding the correct programme for student (#4187) 2024-03-12 17:18:24 +02:00
Riku Rauhala ed0f700fc2 [Study programme] Update text aligns for tables 2024-03-12 13:50:57 +02:00
Riku Rauhala 616cc60b39 [Course population] Fix InfoBox margin 2024-03-12 13:30:30 +02:00
ShootingStar91 68b730a747 Fix faculty programme getter returning multiples of some programmes, causing double credits to be count in progress stats and possibly elsewhere 2024-03-12 13:29:30 +02:00
Riku Rauhala b541857980 [Navigation bar] Format navigation items 2024-03-12 13:26:57 +02:00
Valtteri Kantanen 2b3e436979 [Course population] Clean up extra state and a useEffect 2024-03-12 13:20:22 +02:00
Valtteri Kantanen ba1224c983 [Course population] Use the same logic for credit gains as for programme distribution 2024-03-12 13:15:05 +02:00
Valtteri Kantanen aeab65358d [Course population] Extract logic for finding the correct study programme into its own function 2024-03-12 13:08:52 +02:00
Riku Rauhala e865d12676 [Navigation bar] For dropdown menu items, set the top level item as active 2024-03-12 13:05:27 +02:00
Valtteri Kantanen 96760bd0fb [Course population] Display correct programme if a student has many (#4433) 2024-03-12 12:27:10 +02:00
Riku Rauhala eb7b91a959 [Study programme] Align cells to the right in the By semester tab table 2024-03-12 10:40:03 +02:00
Riku Rauhala e07677ecaa [Study programme] Update chart/table styles 2024-03-11 15:29:50 +02:00
Riku Rauhala d1a729804e [Study programme] Fix countries hover not working properly with 0 value 2024-03-11 15:04:50 +02:00
Riku Rauhala bb1a43ac87 [Study programme] Update students table style to match the one in Faculties 2024-03-11 14:46:00 +02:00
ShootingStar91 d493ac53a5 [Progress stats] Show progamme barchart credits from left to right 2024-03-11 13:48:53 +02:00
Riku Rauhala 0695e031bf Sort props 2024-03-11 13:44:01 +02:00
Riku Rauhala f799420b42 [Faculties] Add missing margin on the Graduation times tab 2024-03-11 10:46:30 +02:00
Riku Rauhala 23a5ee7b08 [Faculties] Align starting year cells to the right 2024-03-11 10:31:08 +02:00
arttu 71b5a87ef1 [University view] Fix credit category titles in expanded table view 2024-03-09 16:42:54 +02:00
Valtteri Kantanen e0b15e457e [Users] Fix logic for filtering out old and specialized programmes 2024-03-08 15:06:50 +02:00
Valtteri Kantanen addacd63c9 [Users] Display a message on user page if they don't have a person id 2024-03-08 15:05:41 +02:00
Riku Rauhala fc8c36392e Update imports 2024-03-08 15:05:03 +02:00
Valtteri Kantanen 1dc2c942f3 Revert "[Users] Move language-related stuff to userRouter"
This reverts commit f5ae6d42e9.
2024-03-08 13:06:58 +02:00
Riku Rauhala cd3ccbf5fb [Faculty statistics] Update styles 2024-03-08 12:49:01 +02:00
Valtteri Kantanen 341b04b01a [Course stats] Fix undeterministic behaviour of combineSubstitutions toggle 2024-03-08 11:49:08 +02:00
Riku Rauhala f826f5b93c [FacultyBarChart] Add the div back 2024-03-08 09:58:22 +02:00
Riku Rauhala 137d48a483 [University] Align content cell text to the right 2024-03-07 22:06:33 +02:00
Riku Rauhala 89f31d5cdf [University] Update styles 2024-03-07 21:51:55 +02:00
arttu 1a8ccde9f3 [Open uni] Fix code that checks if student has degreestudyright 2024-03-07 19:07:57 +02:00
arttu 96a185a59e [Users] Log username if no sufficient rights to see oodikone 2024-03-06 15:01:50 +02:00
arttu 678cd070ec [Updater] Small adjustements to individual student schedule 2024-03-06 12:36:17 +02:00
arttu a606117807 [Custom population] Fix notification showing students that could not be shown to user 2024-03-06 10:29:05 +02:00
ShootingStar91 db9543edd8 Add possibility to schedule individual updates of all students in new programmes 2024-03-05 20:47:24 +02:00
arttu eeeeb1c671 Revert "Add explode backend button & route"
This reverts commit b2b2d87ff3.
2024-03-05 16:11:28 +02:00
ShootingStar91 16b18bb92b [University view] Add include/exclude special studyrights toggle 2024-03-05 14:08:12 +02:00
arttu 2c2f98599e [Credits produced] Add tooptip about transferred credit dates 2024-03-05 12:14:18 +02:00
arttu 1f0b91a612 Revert "[Credits produced] Transfers are again counted to the year of original attainment"
This reverts commit e3151f67d1.
2024-03-05 12:12:06 +02:00
ShootingStar91 e3151f67d1 [Credits produced] Transfers are again counted to the year of original attainment 2024-03-04 13:38:42 +02:00
ShootingStar91 59ab60fc5e [Credits produced] Further improve share resolving code 2024-03-04 13:15:09 +02:00
Riku Rauhala 25233fd13e Disable credits in Highcharts 2024-03-04 13:01:07 +02:00
Riku Rauhala a1e0560faa Rename defaultConfig to config for consistency with other files 2024-03-04 12:53:42 +02:00
Riku Rauhala 7c5c785a6e Get Highcharts href and text from constants 2024-03-04 12:53:42 +02:00
Riku Rauhala 61a4073d82 Move course statistics graph options away from constants 2024-03-04 12:53:42 +02:00
Riku Rauhala d19ef59fc3 Replace the Highcharts default link with toska.dev 2024-03-04 12:53:42 +02:00
Riku Rauhala 986a12c27b Make some minor code style tweaks 2024-03-04 12:53:42 +02:00
Valtteri Kantanen 892a366984 [Users] Replace rights with programmeRights both in backend and frontend 2024-03-01 17:18:45 +02:00
Valtteri Kantanen d87d611db7 [Users] Replace elementDetails with programmeRights 2024-03-01 14:45:53 +02:00
Valtteri Kantanen f5ae6d42e9 [Users] Move language-related stuff to userRouter 2024-03-01 14:45:53 +02:00
Valtteri Kantanen 40af5f0f99 [Users] Add new field to user object: programmeRights 2024-03-01 14:45:53 +02:00
ShootingStar91 e139f4cb4e Fix acual tests 2024-03-01 13:34:12 +02:00
ShootingStar91 71d993246b Revert "Run tests on PR and development"
This reverts commit a3067c6b23.
2024-03-01 13:32:16 +02:00
ShootingStar91 a3067c6b23 Run tests on PR and development 2024-03-01 13:17:26 +02:00
ShootingStar91 01841e104e Fix cypress tests again 2024-03-01 12:06:11 +02:00
ShootingStar91 1ae4c0b39e Fix tests of programme overview 2024-03-01 11:52:56 +02:00
Riku Rauhala 32e4a22c00 [University view] Add missing title 2024-03-01 10:51:32 +02:00
ShootingStar91 013da38a6b Added error listener to frontend: sends errors to sentry if they are not catched by error boundary (event handlers etc) 2024-03-01 10:49:38 +02:00
ShootingStar91 b2b2d87ff3 Add explode backend button & route 2024-03-01 10:48:40 +02:00
arttu 7e22fcd856 [Credits produced] Fix logic: Include Vaasa credits, fix provider resolving, fix determining category 2024-02-29 20:44:56 +02:00
arttu 329466dde9 [Rapodiff] Script changes for investigating every category better 2024-02-29 20:44:56 +02:00
Valtteri Kantanen a7ebc4fb99 Fix containers not being removed after setup 2024-02-28 18:05:17 +02:00
Valtteri Kantanen 6e7ee36db1 [Teachers] Fix doctoral programmes not showing up in the course provider dropdown 2024-02-28 18:03:50 +02:00
Valtteri Kantanen ca8dc45ceb Add ESLint rule for import order 2024-02-27 20:42:37 +02:00
Valtteri Kantanen 9998f2600d Add a weekly cron job for deleting users who haven't logged in for 18 months 2024-02-27 14:43:20 +02:00
Riku Rauhala 1f370ea9c5 [Course statistics] Fix the application crashing while entering course population via the Attempts table 2024-02-27 13:33:16 +02:00
Riku Rauhala f319e3e2a0 [Course statistics] Rearrange imports 2024-02-27 13:32:34 +02:00
Riku Rauhala 01e701b770 [Course population] Rearrange imports 2024-02-27 13:05:50 +02:00
Valtteri Kantanen 4542f4179d Clean up the actionHistory object before sending it to Sentry 2024-02-27 12:29:58 +02:00
Riku Rauhala 288ff2bada Remove duplicate parameters 2024-02-26 19:46:27 +02:00
Valtteri Kantanen dce0642f08 [Teachers] Fix course providers not showing 2024-02-26 14:36:22 +02:00
Valtteri Kantanen c0a1cf99f2 Remove unused file to fix ESLint error 2024-02-26 14:19:47 +02:00
Valtteri Kantanen f4f1ed6818 [Users] Add infobox to user page about IAM based access rights 2024-02-26 14:14:27 +02:00
Valtteri Kantanen e0a7ed139f Fix sorting error 2024-02-26 14:13:35 +02:00
Valtteri Kantanen a5fe61a654 [Users] Remove user faculties from frontend and backend 2024-02-26 14:13:20 +02:00
Valtteri Kantanen d02dff573c [Users] Display IAM group based study programme access rights on user page 2024-02-26 10:58:41 +02:00
Valtteri Kantanen 56faf46a1a [Users] Fix sorting by username 2024-02-26 10:57:51 +02:00
Valtteri Kantanen 9e09168b01 [Sortable table] Fix multi select filter 2024-02-26 10:32:22 +02:00
Riku Rauhala 9d474ca61e [Course statistics] Display enrolled students with no grade in the pass rate chart 2024-02-23 17:03:27 +02:00
Riku Rauhala 9c39f00ec3 Rearrange imports 2024-02-23 13:15:30 +02:00
Riku Rauhala 45d3178193 [Course statistics] Refactor panes 2024-02-23 13:12:01 +02:00
ShootingStar91 ea588e2997 [Faculties] Fix redis-key related issues 2024-02-23 12:33:31 +02:00
ShootingStar91 563e39f6b5 [Updater] Explode frontend button 2024-02-23 11:32:42 +02:00
Valtteri Kantanen a46a9c773d [University view] Fix import 2024-02-23 10:54:56 +02:00
Valtteri Kantanen 6227b5fd81 Replace lazy imports with regular imports 2024-02-23 10:51:04 +02:00
Valtteri Kantanen 653fe445a8 Clean up Highcharts code 2024-02-23 10:50:11 +02:00
arttu cf2931c182 Fix faculty credit refresh 2024-02-22 01:41:59 +02:00
arttu 012e863569 Fix credit computations 2024-02-22 01:36:53 +02:00
ShootingStar91 21207adc94 Studyprogramme overview tests: Fix credit years, as they were changed to show empty years too 2024-02-21 13:26:57 +02:00
ShootingStar91 47193678d9 Credits produced -tables: Don't show the next academic year before it has started 2024-02-21 13:26:25 +02:00
ShootingStar91 021ee51ff2 Fix missing imports 2024-02-21 12:39:22 +02:00
ShootingStar91 51779add4f [Faculties] Credits produced: Made to use rapo categories 2024-02-21 12:35:02 +02:00
ShootingStar91 984d95c236 make rapodiff do a percentage-based diff 2024-02-21 12:32:42 +02:00
Valtteri Kantanen 81b0516b37 [Dependencies] Update minor/patch versions of react-router-dom and xlsx 2024-02-20 19:51:41 +02:00
Valtteri Kantanen c734cf0dce Replace uuid with crypto.randomUUID in the frontend 2024-02-20 19:51:41 +02:00
Valtteri Kantanen bbb7c6b059 Extract logic for generating colors for charts into a util function 2024-02-20 19:51:41 +02:00
Valtteri Kantanen db801b76b6 [ColorizedCoursesTable] Move facultyMap away from context 2024-02-20 19:51:41 +02:00
Riku Rauhala 9e8a92366e Fix InfoBox margins 2024-02-20 14:54:01 +02:00
Riku Rauhala e83acc14b3 [Course statistics] Remove the HelpButton component 2024-02-20 14:15:04 +02:00
Riku Rauhala 5aea071132 [Course statistics] Replace the Help button with the Show info button for charts 2024-02-20 14:15:04 +02:00
Riku Rauhala a0ac892069 [Course statistics] Replace the Help button with the Show info button for tables 2024-02-20 14:15:04 +02:00
Riku Rauhala bd56d13bd8 Remove bottom margin from the InfoBox 2024-02-20 14:15:04 +02:00
Riku Rauhala 22c62db449 Add an option for displaying the InfoBox message as a popup instead 2024-02-20 14:15:04 +02:00
753 changed files with 35261 additions and 26811 deletions
+82
View File
@@ -0,0 +1,82 @@
version: '2'
checks:
argument-count:
enabled: true
config:
threshold: 4
complex-logic:
enabled: true
config:
threshold: 4
file-lines:
enabled: true
config:
threshold: 250
method-complexity:
enabled: true
config:
threshold: 10
method-count:
enabled: true
config:
threshold: 20
method-lines:
enabled: true
config:
threshold: 25
nested-control-flow:
enabled: true
config:
threshold: 4
return-statements:
enabled: false
similar-code:
enabled: true
config:
threshold: # Language-specific defaults. Overrides affect all languages.
identical-code:
enabled: true
config:
threshold: # Language-specific defaults. Overrides affect all languages.
exclude_patterns:
- '.github/'
- '.husky/'
- '.vscode/'
- 'adminer-plugins/'
- 'anonyymioodi/'
- 'cypress/'
- 'documentation/'
- 'scripts/'
- 'services/backend/src/database/migrations_kone/'
- 'services/backend/src/database/migrations_user/'
- 'services/backend/src/models/'
- 'updater/sis-updater-worker/src/db/migrations/'
- 'updater/sis-updater-worker/src/db/models/'
- '.codeclimate.yml'
- '.env.template'
- '.lintstagedrc.js'
- '.nycrc'
- '.prettierrc'
- '.stylelintrc'
- 'cypress.config.js'
- 'LICENSE'
- 'nginx.conf'
- 'nyc-config.js'
- '**/.dockerignore'
- '**/.eslintrc.json'
- '**/.gitignore'
- '**/dev.Dockerfile'
- '**/Dockerfile'
- '**/*.css'
- '**/*.csv'
- '**/*.html'
- '**/*.json'
- '**/*.md'
- '**/*.png'
- '**/*.sh'
- '**/*.sql'
- '**/*.svg'
- '**/*.txt'
- '**/*.yml'
+98 -6
View File
@@ -8,12 +8,104 @@
"ecmaVersion": "latest",
"sourceType": "commonjs"
},
"extends": ["eslint:recommended", "plugin:prettier/recommended", "plugin:cypress/recommended"],
"extends": [
"eslint:recommended",
"airbnb",
"plugin:cypress/recommended",
"plugin:import/recommended",
"plugin:prettier/recommended"
],
"overrides": [
{
"files": ["**/*.ts"],
"env": {
"es2021": true,
"node": true
},
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"airbnb-typescript",
"plugin:prettier/recommended"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 2021,
"sourceType": "module",
"project": true
},
"rules": {
"import/prefer-default-export": "off",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/return-await": "off",
"@typescript-eslint/no-shadow": "off"
}
}
],
"rules": {
"no-console": "error",
"no-async-promise-executor": "off",
"prettier/prettier": "error",
"camelcase": "off",
"consistent-return": "off",
"cypress/no-assigning-return-values": "off",
"cypress/unsafe-to-chain-command": "off"
}
"cypress/unsafe-to-chain-command": "off",
"default-param-last": "off",
"import/extensions": ["error", "never"],
"import/order": [
"error",
{
"alphabetize": { "order": "asc", "caseInsensitive": true },
"groups": [["builtin", "external"], ["internal"], ["parent"], ["sibling", "index"]],
"pathGroups": [
{
"pattern": "../../../**",
"group": "internal",
"position": "before"
},
{
"pattern": "../../**",
"group": "internal",
"position": "after"
},
{
"pattern": "../**",
"group": "parent",
"position": "before"
},
{
"pattern": "./**",
"group": "sibling",
"position": "before"
}
],
"pathGroupsExcludedImportTypes": ["builtin", "external"]
}
],
"no-async-promise-executor": "off",
"no-await-in-loop": "off",
"no-console": "error",
"no-continue": "off",
"no-param-reassign": "off",
"no-plusplus": "off",
"no-promise-executor-return": "off",
"no-restricted-syntax": [
"error",
{
"selector": "ForInStatement",
"message": "for..in loops iterate over the entire prototype chain, which is virtually never what you want. Use Object.{keys,values,entries}, and iterate over the resulting array."
},
"LabeledStatement",
"WithStatement"
],
"no-return-await": "off",
"no-shadow": "off",
"prettier/prettier": "error",
"quotes": ["error", "single", { "avoidEscape": true }]
},
"settings": {
"import/resolver": {
"node": {
"extensions": [".js", ".jsx", ".ts", ".tsx"]
}
}
},
"ignorePatterns": ["build/", "dist/", "instrumented/", "node_modules/", "**/*migrations*/**"]
}
+2 -2
View File
@@ -24,7 +24,7 @@ runs:
- name: 'Run services, pull rest of the needed images'
shell: bash
run: docker-compose --file docker-compose.ci.yml up --detach
run: docker compose --file docker-compose.ci.yml up --detach --quiet-pull
- name: 'Run cypress'
uses: cypress-io/github-action@v6
@@ -44,4 +44,4 @@ runs:
- name: 'Print logs on failure'
shell: bash
if: failure()
run: docker-compose --file docker-compose.ci.yml logs
run: docker compose --file docker-compose.ci.yml logs
-78
View File
@@ -1,78 +0,0 @@
version: 2
updates:
- package-ecosystem: npm
directory: '/'
schedule:
interval: weekly
time: '03:00'
labels:
- 'dependencies'
- 'infra'
allow:
- dependency-type: 'production'
ignore:
- dependency-name: '*'
update-types: ['version-update:semver-major']
- package-ecosystem: npm
directory: '/updater/sis-updater-scheduler'
schedule:
interval: weekly
time: '03:00'
labels:
- 'dependencies'
- 'updater'
allow:
- dependency-type: 'production'
ignore:
- dependency-name: '*'
update-types: ['version-update:semver-major']
- package-ecosystem: npm
directory: '/updater/sis-updater-worker'
schedule:
interval: weekly
time: '03:00'
labels:
- 'dependencies'
- 'updater'
allow:
- dependency-type: 'production'
ignore:
- dependency-name: '*'
update-types: ['version-update:semver-major']
- package-ecosystem: npm
directory: '/services/backend'
schedule:
interval: weekly
time: '03:00'
labels:
- 'dependencies'
- 'back'
allow:
- dependency-type: 'production'
ignore:
- dependency-name: '*'
update-types: ['version-update:semver-major']
- package-ecosystem: npm
directory: '/services/frontend'
schedule:
interval: weekly
time: '03:00'
labels:
- 'dependencies'
- 'front'
allow:
- dependency-type: 'production'
ignore:
- dependency-name: '*'
update-types: ['version-update:semver-major']
- package-ecosystem: 'github-actions'
directory: '/'
schedule:
interval: weekly
time: '03:00'
open-pull-requests-limit: 10
+13 -5
View File
@@ -33,6 +33,7 @@ jobs:
BUILT_AT=${{ steps.get_current_time.outputs.NOW }}
SENTRY_RELEASE=${{ steps.extract_version.outputs.VERSION }}
SENTRY_ENVIRONMENT=production
SENTRY_DSN=${{ secrets.OODIKONE_SENTRY_DSN }}
- name: Push to quay.io
uses: redhat-actions/push-to-registry@v2
@@ -81,6 +82,7 @@ jobs:
runs-on: ubuntu-latest
needs:
- release_frontend
- release_backend
steps:
- uses: actions/checkout@v4
@@ -89,12 +91,18 @@ jobs:
id: extract_version
run: echo "VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
- name: Pull image and create a container
- name: Pull frontend image and create a container
run: docker create --name frontend quay.io/toska/oodikone-frontend:production
- name: Copy assets from the container
- name: Pull backend image and create a container
run: docker create --name backend quay.io/toska/oodikone-backend:production
- name: Copy assets from the frontend container
run: docker cp frontend:/opt/app-root/src/build ./build
- name: Copy assets from the backend container
run: docker cp backend:/opt/app-root/src/dist ./dist
- name: Create Sentry release
uses: getsentry/action-release@v1
env:
@@ -105,7 +113,7 @@ jobs:
with:
environment: production
set_commits: 'skip'
sourcemaps: './build/assets'
sourcemaps: './build/assets ./dist'
url_prefix: '~/assets'
version: ${{ steps.extract_version.outputs.VERSION }}
@@ -122,7 +130,7 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: 'Send notification to slack'
uses: UniversityOfHelsinkiCS/slackbot-action@v1.4.2
uses: UniversityOfHelsinkiCS/slackbot-action@v1.5
with:
webhook-url: ${{ secrets.WEBHOOK_URL }}
message-type: deployment
@@ -142,7 +150,7 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: 'Send notification to slack'
uses: UniversityOfHelsinkiCS/slackbot-action@v1.4.2
uses: UniversityOfHelsinkiCS/slackbot-action@v1.5
with:
webhook-url: ${{ secrets.WEBHOOK_URL }}
message-type: deployment-failure
+73
View File
@@ -0,0 +1,73 @@
name: 'Run tests'
on:
pull_request:
branches:
- master
paths:
- 'cypress/**'
- 'cypress.config.json'
- 'services/**'
- '!services/backend/src/rapodiff/**'
- 'docker-compose.ci.yml'
- 'package*.json'
jobs:
lint_backend_and_frontend:
name: 'Lint backend and frontend'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 18
- name: 'Install dependencies'
run: npm ci && cd services/frontend && npm ci && cd ../backend && npm ci
- name: 'Run Stylelint for CSS files'
run: npm run stylelint "services/frontend/src/**/*.css"
- name: 'Run ESLint for JS files'
run: npm run eslint -- --ext .jsx,.js services --report-unused-disable-directives
test_end_to_end:
runs-on: ubuntu-latest
needs:
- lint_backend_and_frontend
strategy:
fail-fast: false
matrix:
include:
- name: 'Test course statistics'
spec: cypress/e2e/Course_statistics.js
- name: 'Test custom population'
spec: cypress/e2e/Custom_population.js
- name: 'Test population statistics'
spec: cypress/e2e/Population_statistics.js
- name: 'Test filters'
spec: cypress/e2e/Filters.js
- name: 'Test students'
spec: cypress/e2e/Students.js
- name: 'Test completed courses'
spec: cypress/e2e/Completed_courses.js
- name: 'Test studyprogramme overview'
spec: cypress/e2e/Studyprogramme_overview.js
- name: 'Test teachers and users'
spec: |
cypress/e2e/Teachers.js
cypress/e2e/Users.js
- name: 'Test faculty statistics'
spec: cypress/e2e/Faculty_statistics.js
- name: 'Test open uni search'
spec: cypress/e2e/Openuni.js
- name: 'Test language center view'
spec: cypress/e2e/Language_center.js
- name: 'Test study guidance groups'
spec: cypress/e2e/Study_guidance_groups.js
name: ${{ matrix.name }}
steps:
- uses: actions/checkout@v4
- name: 'Run tests'
uses: ./.github/actions/run-tests
with:
username: ${{ secrets.TOSKAREGISTRY_USERNAME }}
password: ${{ secrets.TOSKAREGISTRY_PASSWORD }}
spec: ${{ matrix.spec }}
+12 -25
View File
@@ -12,8 +12,8 @@ on:
jobs:
# === Static tests / linting ===
lint_backend:
name: 'Lint backend'
lint_backend_and_frontend:
name: 'Lint backend and frontend'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
@@ -21,24 +21,11 @@ jobs:
with:
node-version: 18
- name: 'Install dependencies'
run: npm ci && cd services/backend && npm ci
- name: 'Run backend linter'
run: npm run eslint services/backend
lint_frontend:
name: 'Lint frontend'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 18
- name: 'Install dependencies'
run: npm ci && cd services/frontend && npm ci
- name: 'Run frontend linter'
run: npm run concurrently \
'eslint --ext .jsx,.js services/frontend/src --report-unused-disable-directives' \
'stylelint services/frontend/src/**/*.css'
run: npm ci && cd services/frontend && npm ci && cd ../backend && npm ci
- name: 'Run Stylelint for CSS files'
run: npm run stylelint "services/frontend/src/**/*.css"
- name: 'Run ESLint for JS and TS files'
run: npm run eslint -- --ext .js,.jsx,.ts,.tsx services --report-unused-disable-directives
# === Build database images ===
build_backend:
@@ -83,7 +70,7 @@ jobs:
- name: 'Let sis-updater-worker run migrations, then push new version of image to toska hub'
if: steps.check_migrations.outputs.migrations == 'true'
run: |
docker-compose --file docker-compose.ci.yml up --detach sis-updater-worker
docker compose --file docker-compose.ci.yml up --detach sis-updater-worker
sleep 30 # wait for sis-updater-worker to start and run migrations
./anonyymioodi/commit_and_push_to_toska_hub.sh sis-db
@@ -116,7 +103,7 @@ jobs:
- name: 'Let backend run migrations, then push new version of image to toska hub'
if: steps.check_migrations.outputs.migrations == 'true'
run: |
docker-compose --file docker-compose.ci.yml up --detach backend
docker compose --file docker-compose.ci.yml up --detach backend
sleep 30 # wait for sis-updater-worker to start and run migrations
./anonyymioodi/commit_and_push_to_toska_hub.sh kone-db
@@ -149,7 +136,7 @@ jobs:
- name: 'Let backend run migrations, then push new version of image to toska hub'
if: steps.check_migrations.outputs.migrations == 'true'
run: |
docker-compose --file docker-compose.ci.yml up --detach backend
docker compose --file docker-compose.ci.yml up --detach backend
sleep 30 # wait for sis-updater-worker to start and run migrations
./anonyymioodi/commit_and_push_to_toska_hub.sh user-db
@@ -218,7 +205,7 @@ jobs:
password: ${{ secrets.password }}
- name: 'Run services, pull rest of the needed images'
run: docker-compose --file docker-compose.ci.yml up --detach
run: docker compose --file docker-compose.ci.yml up --detach --quiet-pull
- name: 'Check that exit statuses are not errors'
run: |
@@ -230,4 +217,4 @@ jobs:
- name: 'Print logs on failure'
if: failure()
run: docker-compose --file docker-compose.ci.yml logs
run: docker compose --file docker-compose.ci.yml logs
+28 -7
View File
@@ -1,4 +1,4 @@
name: 'Test and release Updater'
name: 'Test (and release) Updater'
on:
push:
@@ -8,8 +8,27 @@ on:
- '.github/workflows/updater.yaml'
- 'updater/sis-updater-worker/**'
- 'updater/sis-updater-scheduler/**'
pull_request:
branches:
- master
paths:
- 'updater/sis-updater-worker/**'
- 'updater/sis-updater-scheduler/**'
jobs:
lint_scheduler_and_worker:
name: 'Lint scheduler and worker'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 18
- name: 'Install dependencies'
run: npm ci && cd updater/sis-updater-scheduler && npm ci && cd ../sis-updater-worker && npm ci
- name: 'Run linter'
run: npm run eslint updater -- --report-unused-disable-directives
build_worker:
name: 'Build Updater worker'
runs-on: ubuntu-latest
@@ -50,6 +69,7 @@ jobs:
name: 'Test Updater'
runs-on: ubuntu-latest
needs:
- lint_scheduler_and_worker
- build_worker
- build_scheduler
steps:
@@ -69,24 +89,24 @@ jobs:
- name: 'Load scheduler image'
run: docker load --input /tmp/artifact/scheduler.tar
- name: 'Start worker'
run: docker-compose --file docker-compose.ci.yml up --detach --no-recreate sis-updater-worker
run: docker compose --file docker-compose.ci.yml up --detach --no-recreate sis-updater-worker
- name: 'Run hourly jobs'
run: docker-compose --file docker-compose.ci.yml run sis-updater-scheduler npm start
run: docker compose --file docker-compose.ci.yml run sis-updater-scheduler npm start
env:
SCHEDULE_IMMEDIATE: hourly
EXIT_AFTER_IMMEDIATES: yes
- name: 'Run weekly jobs'
run: docker-compose --file docker-compose.ci.yml run sis-updater-scheduler npm start
run: docker compose --file docker-compose.ci.yml run sis-updater-scheduler npm start
env:
SCHEDULE_IMMEDIATE: weekly
EXIT_AFTER_IMMEDIATES: yes
- name: 'Run prepurge'
run: docker-compose --file docker-compose.ci.yml run sis-updater-scheduler npm start
run: docker compose --file docker-compose.ci.yml run sis-updater-scheduler npm start
env:
SCHEDULE_IMMEDIATE: prepurge
EXIT_AFTER_IMMEDIATES: yes
- name: 'Run purge'
run: docker-compose --file docker-compose.ci.yml run sis-updater-scheduler npm start
run: docker compose --file docker-compose.ci.yml run sis-updater-scheduler npm start
env:
SCHEDULE_IMMEDIATE: purge
EXIT_AFTER_IMMEDIATES: yes
@@ -95,6 +115,7 @@ jobs:
name: 'Build and release Updater worker'
runs-on: ubuntu-latest
needs: test_updater
if: github.event_name == 'push'
steps:
- uses: actions/checkout@v4
@@ -121,7 +142,7 @@ jobs:
name: 'Build and release Updater scheduler'
runs-on: ubuntu-latest
needs: test_updater
if: github.event_name == 'push'
steps:
- uses: actions/checkout@v4
+24 -9
View File
@@ -16,16 +16,12 @@ pids
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# Production
dist/
# Dependency directories
node_modules/
jspm_packages/
node_modules/
# Optional npm cache directory
.npm
@@ -39,10 +35,29 @@ jspm_packages/
# Output of 'npm pack'
*.tgz
# dotenv environment variables file
# Misc
*.sqz
# Environment variable files
.env
.env.test
.env.production
# Oodikone related stuff
.databasedumps
.databasedumps/
# Cypress
cypress/downloads/
cypress/screenshots/
cypress/videos/
# Code coverage
.nyc_output/
coverage/
instrumented/
# pycharm
.idea
# fd specific
environments/
-1
View File
@@ -1 +0,0 @@
_
-3
View File
@@ -1,6 +1,3 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
npx lint-staged
if git grep -qE --cached "(it|describe)\.only" $(git diff --cached --name-only) ./cypress; then
+3 -2
View File
@@ -4,8 +4,9 @@ const dockerCmdBase = `docker run --rm --volume ${cwd}:/oodikone --workdir /oodi
const relativeFilePaths = files => [...files.map(file => path.relative(cwd, file))].join(' ')
module.exports = {
'{services,updater}/**/*.{js,jsx}': files => `eslint --fix ${files.join(' ')} --report-unused-disable-directives`,
'*.{js,json,md,yml,yaml,html,css}': files => `prettier --write ${files.join(' ')}`,
'{services,updater}/**/*.{js,jsx,ts,tsx}': files =>
`eslint --fix ${files.join(' ')} --report-unused-disable-directives`,
'*.{js,jsx,ts,tsx,json,md,yml,yaml,html,css}': files => `prettier --write ${files.join(' ')}`,
'*.css': files => `stylelint --fix ${files.join(' ')}`,
Dockerfile: files =>
`${dockerCmdBase} hadolint/hadolint:v2.12.0 hadolint --ignore DL3006 ${relativeFilePaths(files)}`,
+5
View File
@@ -0,0 +1,5 @@
{
"all": true,
"include": ["services/frontend/src/**/*.js", "services/frontend/src/**/*.jsx"],
"extends": "./nyc-config.js"
}
+62 -47
View File
@@ -6,21 +6,23 @@ An application for analyzing university data, running at [https://oodikone.helsi
To run Oodikone locally, you will need the following:
1. Applications:
- [Docker](https://docs.docker.com/install/) (version 20.10+),
- [Docker Compose](https://docs.docker.com/compose/install/) (version 1.29+) and
- [npm](https://docs.npmjs.com/cli/v7) (version 7+)
2. Access to Toska Docker Hub,
3. For real data setup, access to Toskas production servers.
4. For some features to work, access to Toskas service tokens
1. Applications
- [Docker](https://docs.docker.com/install/) (version `20.10+`),
- [Docker Compose](https://docs.docker.com/compose/install/) (version `1.29+`)
- [npm](https://docs.npmjs.com/cli/v7) (version `7+`)
2. Access to Toska Docker Hub
3. For real data setup, access to Toska's production servers
4. For some features to work, access to Toska's service tokens
## 🚀 Installation
Pre-installation steps:
- Clone this repo
- Login to toskas docker hub (see Toskas Gitlab for more information)
- Populate `.env.template` file with correct tokens and rename it to `.env`
- `git@github.com:UniversityOfHelsinkiCS/oodikone.git`
- Login to Toska's Docker Hub (see Toska's GitLab for more information)
- Copy the `.env.template` file to `.env` and populate with correct tokens
- `cp .env.template .env`
Then launch the CLI and follow the instructions:
@@ -32,23 +34,26 @@ _Please use a terminal at least 80 characters wide, the CLI is a bit rudimentary
What different CLI options do:
1. Set up oodikone from scratch:
1. Set up Oodikone from scratch
- Cleans up any previous installations
- Installs all needed npm packages locally
- Sets up pre-commit linting hooks.
- Pulls and builds all needed Docker images and sets up dockerized development environment.
- Setup happens with anonymized data, which developers should use by default.
- **Note:** Running this option cleans up all real data too, so please don't run option 2 before this.
2. Reset all real data:
- Sets up pre-commit linting hooks
- Pulls and builds all needed Docker images and sets up dockerized development environment
- Setup happens with anonymized data, which developers should use by default
- **Note:** Running this option cleans up all real data too, so please don' run option 2 before this.
2. Reset all real data
- Cleans up any previous real data databases
- Downloads needed database dumps from production servers.
- Creates real data databases and populates them with downloaded dumps.
3. Reset single database
- Like option 2, but only for single database. Leaves other databases untouched.
3. Reset a single database
- Like option 2, but only for single database
- Leaves other databases untouched
4. Restore data from dumps
- Like option 2, but skips downloading, and simply restores databases from the dumps downloaded earlier.
- Like option 2, but skips downloading, and simply restores databases from the dumps downloaded earlier
5. Docker system prune
- Runs `docker system prune -a && docker volume prune -a`. This will remove all your docker data, also related to any other applications than oodikone! It is sometimes necessary after strange errors due to caching.
- Runs `docker system prune -a && docker volume prune -a`
- This will remove all your Docker data, also related to any other applications than Oodikone!
- Sometimes necessary after strange errors due to caching
## ⌨️ Development
@@ -94,56 +99,68 @@ graph TB
end
```
In development, backend and updater use the same redis, but in production they are separate.
In development, backend and updater use the same Redis, but in production they are separate.
See also [older graph](documentation/Oodikone.png), which presents more information.
See also the [older graph](documentation/img/oodikone.png) for more information.
To read a bit more details about what updater-scheduler and updater-worker do, see their own READMEs:
- [updater-scheduler's README](./updater/sis-updater-scheduler/README.md)
- [updater-worker's README](./updater/sis-updater-worker/README.md)
### Documentation
Folder `documentation` currently contains some notes on sis-db schema and is meant as a place for storing useful information on Oodikone to make life easier for future developers. Feel free to add anything relevant!
The `documentation` directory contains some notes on the sis-db schema and is meant as a place for storing useful information on Oodikone to make life easier for future developers. Feel free to add anything relevant!
For internal meeting notes and sensitive information, see Toska GitLab.
[SortableTable documentation](./services/frontend/src/components/SortableTable/README.md)
### Basics
The development environment is entirely configured in the `docker-compose.yml` file located in this repository. The file defines the services for oodikone's two main components: **oodikone** and **updater**.
The development environment is entirely configured in the `docker-compose.yml` file located in this repository. The file defines the services for Oodikone's two main components: **oodikone** and **updater**.
Running oodikone with real data requires separated databases and redis, which are defined in `docker-compose.real.yml` file. Otherwise real data development environment uses the configuration as anonymized data development environment.
Running Oodikone with real data requires separated databases and redis, which are defined in `docker-compose.real.yml` file. Otherwise real data development environment uses the configuration as anonymized data development environment.
Some useful commands are defined in `package.json` and can be run with `npm run <command>` as follows:
- `npm run oodikone`: starts oodikone with anonymized data
- `npm run oodikone:real`: starts oodikone with real data
- `npm run oodikone`: starts Oodikone with anonymized data
- `npm run oodikone:real`: starts Oodikone with real data
- `npm run updater`: starts updater with anonymized data
- `npm run updater:real`: starts oodikone with real data
- `npm run both`: starts oodikone and updater with anonymized data
- `npm run both:real`: starts oodikone and updater with real data
- `npm run updater:real`: starts updater with real data
- `npm run both`: starts Oodikone and updater with anonymized data
- `npm run both:real`: starts Oodikone and updater with real data
- `npm run docker:down`: stops the whole environment
- `npm run testupdater`: runs tests for updater
- `npm run flushredis`: Clears redis, which forces big calculations to be redone in e.g. studyprogramme overview and faculty views.
- `npm run flushredis`: clears Redis, which forces big calculations to be redone in e.g. studyprogramme overview and faculty views
- `npm run rapodiff`: runs [Rapodiff](./services/backend/src/rapodiff/)
- `npm run install:local`: installs `node_modules` for each package (backend, frontend, sis-updater-scheduler and sis-updater-worker) locally
- `npm run install:docker`: installs `node_modules` for each package inside containers
- `npm run install:both`: runs both `npm run install:local` and `npm run install:docker`
Once you have ran setup for oodikone , you can just execute the first one (`npm run oodikone`). After starting and waiting for a while for containers to compile, oodikone can be accessed at [http://localhost:3000/](http://localhost:3000/) and Adminer (database investigation tool) at [http://localhost:5050/](http://localhost:5050/). Adminer requires you to login with username `postgres` and with any password you choose (for example `p`).
Once you have ran setup for Oodikone , you can just execute the first one (`npm run oodikone`). After starting and waiting for a while for containers to compile, Oodikone can be accessed at [http://localhost:3000](http://localhost:3000/) and Adminer (database investigation tool) at [http://localhost:5050](http://localhost:5050/). Adminer requires you to login with username `postgres` and with any password you choose (for example `p`).
### Run.sh script
As said, the development environment runs entirely inside docker containers. To keep `package.json` clean and not filled with predefined scripts, we have created a simple helper script called `./run.sh`. The script allows you to use docker-compose commands without the need to write long list of parameters. Try to run `./run.sh` in the root of the project and see what happens!
As said, the development environment runs entirely inside Docker containers. To keep `package.json` clean and not filled with predefined scripts, we have created a simple helper script called `./run.sh`. The script allows you to use docker-compose commands without the need to write long list of parameters. Try to run `./run.sh` in the root of the project and see what happens!
`./run.sh` is simply a wrapper script to run oodikone, updater or both services in either anon or real mode. If you take a look at `package.json`, you can see that most of the predefined scripts above use `./run.sh` under the hood.
`./run.sh` is simply a wrapper script to run Oodikone, updater or both services in either anon or real mode. If you take a look at `package.json`, you can see that most of the predefined scripts above use `./run.sh` under the hood.
It is recommended to spend some time to become familiar with `docker` and `docker compose` cli commands. You can then use them directly or with `./run.sh` wrapper. Here is some examples for day-to-day development situations:
- `./run.sh oodikone anon pull`: Pull all images related to oodikone development
- `./run.sh updater real up --build --force-recreate --detach`: Start updater detached (=in the background) in real data mode, but build new images before starting
- `./run.sh oodikone anon pull`: pull all images related to Oodikone development
- `./run.sh updater real up --build --force-recreate --detach`: start updater detached (in the background) in real data mode, but build new images before starting
- `docker compose ps`: view the containers in the running environment
- `docker compose logs frontend`: print logs for just frontend
- `docker compose logs --follow --tail 100 backend`: print last hundred rows of backend logs and begin to follow them in your terminal window
- `docker exec -it backend sh`: open bash terminal inside backend container
- `docker exec -it sis-db psql -U postgres sis-db-real`: open psql client to investigate sis real data database.
- `docker exec -it sis-db psql -U postgres sis-db-real`: open psql client to investigate sis real data database
### User types for development
By default, you're login as `mluukkai` dev user when running oodikone in development mode. If you want to debug with certain type of user, you can use mocking: go to "Users" -page, click on "edit" on user you want to use and then click icon on the right corner of user card. Another way is to mock user headers - see frontend's api configuration for how this is done.
By default, you're login as `mluukkai` dev user when running Oodikone in development mode. If you want to debug with certain type of user, you can use mocking: go to the "Users" page, click "edit" on the user you want to use and then click the icon on the right corner of user card. Another way is to mock user headers - see frontend's API configuration for how this is done.
Anon data contains some preset user types, corresponding to most usual user types in real data. These are used in testing too (see "Testing" below for more info).
Anonymous data contains some preset user types, corresponding to most usual user types in real data. These are used in testing too (see "Testing" below for more info).
### Linting
@@ -169,8 +186,8 @@ Continuous integration (CI) works with Github actions and is defined in workflow
- Oodikone setup for cypress and other tests in CI is defined in `docker-compose.ci.yml`. Take a look at this too if debugging github action workflows.
- Tests are run on every push
- After a successful test run, oodikone is deployed to staging
- After creating a release, oodikone is deployed to production
- After a successful test run, Oodikone is deployed to staging
- After creating a release, Oodikone is deployed to production
- Updater is deployed to production when pushed if tests pass
- Test databases can be updated, instructions in [anonyymioodi README](anonyymioodi/README.md)
@@ -180,7 +197,7 @@ Continuous integration (CI) works with Github actions and is defined in workflow
### Modules are missing after updating package.json
You should always install the dependencies **inside** the container to have the application **inside** the container access them. Module might be missing for example when someone else installs a new library and you only pull the changes in package.json. Use `docker exec <service> npm ci` to install modules inside the container.
You should always install the dependencies **inside** the container to have the application **inside** the container access them. Module might be missing for example when someone else installs a new library and you only pull the changes in package.json. Use `docker exec <service> npm ci` to install modules inside the container or `npm run install:docker` to install modules inside all packages (backend, frontend, sis-updater-scheduler and sis-updater-worker).
### Studyguidance groups don't work on my machine
@@ -190,14 +207,12 @@ Make sure you have your VPN on.
First: Try `npm run cli` option 1: _Set up oodikone from scratch_ and then option 2 to download and restore databases (or option 4 to skip downloading, if you've done it recently).
If that does not help, try option 5: _Docker system prune_. Notice that this clears up **all docker data**, including data related to other projects. If this is not ok, you'll need to identify the oodikone-specific docker volumes yourself and caches and clear those invididually.
If that does not help, try option 5: _Docker system prune_. Notice that this clears up **all Docker data**, including data related to other projects. If this is not ok, you'll need to identify the Oodikone-specific Docker volumes yourself and caches and clear those invididually.
## ✌🏼 Maintainers and contribution
[Toska](https://toska.dev) of course.
[Toska](https://toska.dev) - University of Helsinki
University of Helsinki
## 🛡️ Tietosuoja / data protection
## Tietosuoja / data protection
See [tietosuoja.md](tietosuoja.md).
See [tietosuoja.md](./documentation/tietosuoja.md).
-2
View File
@@ -1,2 +0,0 @@
*.sqz
+4 -4
View File
@@ -9,7 +9,7 @@ services:
PGDATA: /data
POSTGRES_DB: kone-db
POSTGRES_HOST_AUTH_METHOD: trust
image: postgres:15.3
image: postgres:15.7
profiles:
- oodikone
@@ -20,7 +20,7 @@ services:
PGDATA: /data
POSTGRES_DB: sis-db
POSTGRES_HOST_AUTH_METHOD: trust
image: postgres:15.3
image: postgres:15.7
shm_size: 2gb
sis-importer-db:
@@ -30,7 +30,7 @@ services:
PGDATA: /data
POSTGRES_DB: sis-importer-db
POSTGRES_HOST_AUTH_METHOD: trust
image: postgres:15.3
image: postgres:15.7
profiles:
- updater
@@ -41,6 +41,6 @@ services:
PGDATA: /data
POSTGRES_DB: user-db
POSTGRES_HOST_AUTH_METHOD: trust
image: postgres:15.3
image: postgres:15.7
profiles:
- oodikone
+1 -1
View File
@@ -22,7 +22,7 @@ trap cleanup SIGINT SIGTERM ERR EXIT
cleanup() {
trap - SIGINT SIGTERM ERR EXIT
warningmsg "Trying to run docker-compose down and remove orphans"
docker-compose down --remove-orphans
docker-compose --profile oodikone --profile updater down --remove-orphans
}
# === CLI ===
+7 -1
View File
@@ -1,3 +1,7 @@
/* eslint-disable global-require */
/* eslint-disable import/extensions */
/* eslint-disable import/no-extraneous-dependencies */
const { defineConfig } = require('cypress')
module.exports = defineConfig({
@@ -11,7 +15,9 @@ module.exports = defineConfig({
// We've imported your old cypress plugins here.
// You may want to clean this up later by importing these.
setupNodeEvents(on, config) {
return require('./cypress/plugins/index.js')(on, config)
require('@cypress/code-coverage/task')(on, config)
require('./cypress/plugins/index.js')(on, config)
return config
},
baseUrl: 'http://localhost:3000',
specPattern: 'cypress/e2e/**/*.{js,jsx,ts,tsx}',
-2
View File
@@ -1,2 +0,0 @@
screenshots
videos
+10 -10
View File
@@ -4,6 +4,13 @@ const openCompletedCoursesModal = () => {
cy.get('button').contains('Search completed courses of students').click()
}
const hasLanded = () => {
cy.contains('Search completed courses')
cy.contains(
'Here you can search by a list of student and course numbers to see whether students have completed certain courses yet'
)
}
const openSearch = () => {
cy.init('/completedcoursessearch')
hasLanded()
@@ -12,13 +19,6 @@ const selectSavedCourselist = name => {
cy.get('[data-cy="history-search"]').children().eq(0).type(name).type('{enter}')
}
const hasLanded = () => {
cy.contains('Search completed courses')
cy.contains(
'Here you can search by a list of student and course numbers to see whether students have completed certain courses yet'
)
}
const deleteAllSearches = () => {
cy.contains('Saved courselists')
.get('.dropdown')
@@ -67,7 +67,7 @@ describe('When search modal is opened', () => {
)
cy.get('[data-cy="rights-notification"]').should('contain.text', '1')
cy.get('[data-cy="completed-courses-table-div"]').should('contain.text', 'Completed courses search')
cy.get('[data-cy="completed-courses-table-div"]').should('contain.text', 'Student Number')
cy.get('[data-cy="completed-courses-table-div"]').should('contain.text', 'Student number')
cy.get('[data-cy="completed-courses-table-div"]').should('not.contain', '1')
})
})
@@ -143,11 +143,11 @@ describe('Courselist saving-related functions work', () => {
openSearch()
openCompletedCoursesModal()
selectSavedCourselist(courseListNames[0])
cy.get('[data-cy="course-list-input"]').type(`,TKT10001`)
cy.get('[data-cy="course-list-input"]').type(',TKT10001')
cy.get('button').contains('Save').click()
openSearch()
openCompletedCoursesModal()
selectSavedCourselist(courseListNames[0])
cy.get('[data-cy="course-list-input"]').contains(`TKT10001`)
cy.get('[data-cy="course-list-input"]').contains('TKT10001')
})
})
+68 -60
View File
@@ -1,15 +1,13 @@
/// <reference types="Cypress" />
const openCustomPopupForm = () => {
cy.get('button').contains('Custom population').click()
cy.get('[data-cy="custom-pop-search-button"]').click()
}
const fillName = () => {
const name = `TEST-${new Date().getTime()}`
cy.contains('Insert name for this custom population if you wish to save it')
.siblings()
.get('input[placeholder=name]')
.type(name)
cy.get('[data-cy="custom-population-name-input"]').type(name)
return name
}
@@ -40,20 +38,17 @@ const deleteAllSearches = () => {
})
}
const fillForm = content => {
cy.contains('Insert student numbers you wish to use for population here')
.siblings()
.get('textarea')
.type(content.join('\n'))
const fillForm = (content, separator) => {
cy.get('[data-cy="student-number-input"]').type(content.join(separator))
}
const search = () => {
cy.get('button').contains('Search population').click()
cy.get('[data-cy="search-button"]').click()
}
const searchFor = studentnumbers => {
const searchFor = (studentnumbers, separator) => {
openCustomPopupForm()
fillForm(studentnumbers)
fillForm(studentnumbers, separator)
search()
}
@@ -74,8 +69,19 @@ const containsSpecificStudents = (studentnumbers = []) => {
studentnumbers.forEach(s => cy.contains(s))
}
const checkRightsNotification = studentNumbers => {
cy.get('[data-cy="rights-notification"]').within(() => {
cy.contains(
'The following students information could not be displayed. This could be either because they do not exist, or you do not have the right to view their information.'
)
cy.get('ul').within(() => {
studentNumbers.forEach(number => cy.get('li').contains(number))
})
})
}
describe('Custom population tests', () => {
const nonExistentStudentNumbers = ['123', 'X', '-', ' ']
const nonExistentStudentNumbers = ['123', 'X', '-']
beforeEach(() => {
cy.init('/custompopulation')
cy.url().should('include', '/custompopulation')
@@ -83,7 +89,7 @@ describe('Custom population tests', () => {
})
after(() => {
cy.visit(`${Cypress.config().baseUrl}/custompopulation`)
cy.visit('/custompopulation')
cy.url().should('include', '/custompopulation')
cy.contains('Custom population')
cy.get('button').contains('Custom population').click()
@@ -92,9 +98,8 @@ describe('Custom population tests', () => {
describe('Custom population searching', () => {
it('Finds a proper population', () => {
cy.fixture('customPopulations').then(({ studentNumbersForCSStudentsSet1 }) => {
const students = studentNumbersForCSStudentsSet1
searchFor(students)
cy.fixture('customPopulations').then(({ studentNumbersForCSStudentsSet1: students }) => {
searchFor(students, '\n')
hasLanded()
containsAmountOfStudents(students.length)
containsSpecificStudents(students)
@@ -102,17 +107,18 @@ describe('Custom population tests', () => {
})
it("Doesn't return non-existing students", () => {
cy.fixture('customPopulations').then(({ studentNumbersForCSStudentsSet1 }) => {
const students = [...studentNumbersForCSStudentsSet1, ...nonExistentStudentNumbers]
searchFor(students)
cy.fixture('customPopulations').then(({ studentNumbersForCSStudentsSet1: students }) => {
searchFor([...students, ...nonExistentStudentNumbers], ' ')
hasLanded()
containsAmountOfStudents(studentNumbersForCSStudentsSet1.length)
containsSpecificStudents(studentNumbersForCSStudentsSet1)
containsAmountOfStudents(students.length)
containsSpecificStudents(students)
checkRightsNotification(nonExistentStudentNumbers)
})
})
it("Doesn't find empty custom population", () => {
searchFor(nonExistentStudentNumbers)
searchFor(nonExistentStudentNumbers, ',')
checkRightsNotification(nonExistentStudentNumbers)
cy.contains('Credit accumulation').should('not.exist')
cy.contains('Programme distribution').should('not.exist')
cy.contains('Courses of population').should('not.exist')
@@ -120,10 +126,11 @@ describe('Custom population tests', () => {
})
it("Doesn't return students user has no right to", () => {
// TODO: check that this doesn't create false positives, since this test goes
// through even if following students are not in anon sis-db.
// These students exist in the database, but the user doesn't have the right to view them
const studentsForEduBachStudents = ['014990067', '013069465', '014853890']
searchFor(studentsForEduBachStudents)
// Two semicolons on purpose, the page should be able to handle it
searchFor(studentsForEduBachStudents, ';;')
checkRightsNotification(studentsForEduBachStudents)
cy.contains('Credit accumulation').should('not.exist')
cy.contains('Programme distribution').should('not.exist')
cy.contains('Courses of population').should('not.exist')
@@ -132,12 +139,15 @@ describe('Custom population tests', () => {
})
describe('Custom population search saving', () => {
it('Saves a custom population search', () => {
cy.fixture('customPopulations').then(({ studentNumbersForCSStudentsSet1 }) => {
const students = studentNumbersForCSStudentsSet1
it('Saves a custom population search', { retries: 2 }, () => {
cy.fixture('customPopulations').then(({ studentNumbersForCSStudentsSet1: students }) => {
openCustomPopupForm()
cy.contains(
'Insert student numbers you wish to use for population. Separate each number with a comma, semicolon, space, or newline.'
)
const name = fillName()
fillForm(students)
// A comma and a newline on purpose, the page should be able to handle it
fillForm(students, ',\n')
save()
// Round 1
@@ -148,10 +158,9 @@ describe('Custom population tests', () => {
containsSpecificStudents(students)
// Round 2
cy.visit(`${Cypress.config().baseUrl}/custompopulation`)
cy.url().should('include', '/custompopulation')
cy.visit('/custompopulation')
cy.contains('Custom population')
cy.get('button').contains('Custom population').click()
openCustomPopupForm()
selectSavedPopulation(name)
search()
cy.contains(`Custom population "${name}"`)
@@ -161,35 +170,34 @@ describe('Custom population tests', () => {
})
it('Updates a custom population search', () => {
cy.fixture('customPopulations').then(({ studentNumbersForCSStudentsSet1, studentNumbersForCSStudentsSet2 }) => {
const students1 = studentNumbersForCSStudentsSet1
const students2 = studentNumbersForCSStudentsSet2
openCustomPopupForm()
const name = fillName()
fillForm(students1)
save()
cy.fixture('customPopulations').then(
({ studentNumbersForCSStudentsSet1: students1, studentNumbersForCSStudentsSet2: students2 }) => {
openCustomPopupForm()
const name = fillName()
fillForm(students1, ' ')
save()
selectSavedPopulation(name)
search()
cy.contains(`Custom population "${name}"`)
containsAmountOfStudents(students1.length)
containsSpecificStudents(students1)
cy.contains('Custom population')
cy.get('button').contains('Custom population').click()
selectSavedPopulation(name)
fillForm([...students1, ...students2])
save()
selectSavedPopulation(name)
search()
cy.contains(`Custom population "${name}"`)
containsAmountOfStudents(students1.length)
containsSpecificStudents(students1)
cy.contains('Custom population')
openCustomPopupForm()
selectSavedPopulation(name)
fillForm(['\n', ...students2], ', ')
save()
cy.visit(`${Cypress.config().baseUrl}/custompopulation`)
cy.url().should('include', '/custompopulation')
cy.contains('Custom population')
cy.get('button').contains('Custom population').click()
selectSavedPopulation(name)
search()
cy.contains(`Custom population "${name}"`)
containsAmountOfStudents(students1.length + students2.length)
containsSpecificStudents([...students1, ...students2])
})
cy.visit('/custompopulation')
cy.contains('Custom population')
openCustomPopupForm()
selectSavedPopulation(name)
search()
cy.contains(`Custom population "${name}"`)
containsAmountOfStudents(students1.length + students2.length)
containsSpecificStudents([...students1, ...students2])
}
)
})
})
})
+49 -19
View File
@@ -1,21 +1,27 @@
/// <reference types="Cypress" />
const path = require('path')
const timestamp = new Date().toISOString().split('T')[0] // YYYY-MM-DD
const downloadsFolder = Cypress.config('downloadsFolder')
describe('Faculty overview', () => {
describe('Faculty can be selected', () => {
it('Faculties are listed and one can be chosen', () => {
cy.init('/faculties')
cy.get('[data-cy=select-faculty]').contains('td', 'H10')
cy.contains('td', 'H99').should('not.exist')
cy.contains('td', 'H90').click()
cy.contains('.header', 'Eläinlääketieteellinen tiedekunta')
cy.get('[data-cy=select-faculty]').contains('a', 'Teologinen tiedekunta')
cy.contains('a', 'H99').should('not.exist')
cy.contains('a', 'Teologinen tiedekunta').click()
cy.contains('.header', 'Teologinen tiedekunta')
})
})
describe('Faculty basic information: admin user', () => {
describe('Basic information: admin user', () => {
beforeEach(() => {
cy.init('/faculties', 'admin')
cy.contains('td', 'H90').click()
cy.contains('a', 'Eläinlääketieteellinen tiedekunta').click()
})
it('Credits produced by faculty are shown', () => {
cy.get('[data-cy="Section-CreditsProducedByTheFaculty"]').should('be.visible')
cy.get('[data-cy="Graph-CreditsProducedByTheFaculty"]').should('be.visible')
@@ -26,11 +32,12 @@ describe('Faculty overview', () => {
})
})
describe('Faculty basic information: basic user', () => {
describe('Basic information: basic user', () => {
beforeEach(() => {
cy.init('/faculties')
cy.contains('td', 'H80').click()
cy.contains('a', 'Maatalous-metsätieteellinen tiedekunta').click()
})
it('Basic information tab show all graphs and tables', () => {
cy.get('[data-cy="Table-CreditsProducedByTheFaculty"]').should('be.visible')
cy.get('[data-cy="Graph-CreditsProducedByTheFaculty"]').should('be.visible')
@@ -74,12 +81,29 @@ describe('Faculty overview', () => {
cy.get('[data-cy="StudentsOfTheFaculty-close-info"]').click()
cy.get('[data-cy="StudentsOfTheFaculty-info-content"]').should('not.exist')
})
it('Data can be exported to Excel files', () => {
const sections = [
'StudentsOfTheFaculty',
'GraduatedOfTheFaculty',
'ThesisWritersOfTheFaculty',
'CreditsProducedByTheFaculty',
]
sections.forEach(section => {
cy.get(`[data-cy="Graph-${section}"]`).within(() => {
cy.get('[aria-label="View chart menu, Chart"]').click()
cy.contains('li.highcharts-menu-item', 'Download XLS').click()
const downloadedFile = `oodikone_${section}_H80_${timestamp}.xls`
cy.readFile(path.join(downloadsFolder, downloadedFile))
})
})
})
})
describe('Study programme information: users with access', () => {
beforeEach(() => {
cy.init('/faculties')
cy.contains('td', 'H80').click()
cy.contains('a', 'Maatalous-metsätieteellinen tiedekunta').click()
})
it('Study programme credit information is not visible in the beginning', () => {
@@ -131,7 +155,7 @@ describe('Faculty overview', () => {
describe('Average graduation times', () => {
beforeEach(() => {
cy.init('/faculties')
cy.contains('td', 'H60').click()
cy.contains('a', 'Kasvatustieteellinen tiedekunta').click()
cy.contains('Graduation times').click()
})
@@ -140,7 +164,7 @@ describe('Faculty overview', () => {
cy.get('[data-cy="Section-bachelor"]').should('be.visible')
cy.get('[data-cy="Section-master"]').should('be.visible')
cy.get('[data-cy="Section-master"]').within(() => {
cy.contains('Graduation year').should('be.visible')
cy.contains('text.highcharts-axis-title', 'Graduation year')
cy.contains('.message', "Click a bar to view that year's programme level breakdown").should('be.visible')
})
})
@@ -166,7 +190,7 @@ describe('Faculty overview', () => {
cy.get('div[class="programmes-graph"]').should('be.visible')
cy.get('div[class="programmes-graph"]').within(() => {
cy.contains('EDUK')
cy.contains('1 graduated').trigger('mouseover')
cy.get('[aria-label="EDUK, 40."]').trigger('mouseover')
cy.contains('Kasvatustieteiden kandiohjelma')
cy.contains('KH60_001')
})
@@ -187,7 +211,7 @@ describe('Faculty overview', () => {
cy.get('div[class="programmes-graph"]').should('be.visible')
cy.get('div[class="programmes-graph"]').within(() => {
cy.contains('EDUM')
cy.contains('24 graduated').trigger('mouseover')
cy.get('[aria-label="EDUM, 22."]').trigger('mouseover')
cy.contains('Kasvatustieteiden maisteriohjelma')
cy.contains('MH60_001')
})
@@ -209,23 +233,29 @@ describe('Faculty overview', () => {
cy.get('[data-cy="GraduationTimeToggle"]').click()
cy.get('[data-cy="Section-master"]').within(() => {
cy.contains('16').click()
cy.get('[aria-label="2018, 16. On time."]').click()
cy.get('div[class="programmes-breakdown-graph"]').should('be.visible')
cy.get('div[class="programmes-breakdown-graph"]').within(() => {
cy.contains('Year 2018 by start year')
cy.contains('EDUM')
cy.contains('16').trigger('mouseover')
cy.get('[aria-label="EDUM, 3. Max. year overtime."]').trigger('mouseover')
cy.contains('Kasvatustieteiden maisteriohjelma')
cy.contains('MH60_001')
})
})
})
it('Data can be exported to an Excel file', () => {
cy.get('[data-cy="DownloadButton-AverageGraduationTimes"]').click()
const downloadedFile = `oodikone_H60_graduation_times_${timestamp}.xlsx`
cy.readFile(path.join(downloadsFolder, downloadedFile))
})
})
describe('Faculty Progress and student population -tab', () => {
describe('Faculty Progress and student population tab', () => {
beforeEach(() => {
cy.init('/faculties')
cy.contains('td', 'H50').click()
cy.contains('a', 'Matemaattis-luonnontieteellinen tiedekunta').click()
cy.contains('Programmes and student populations').click()
})
@@ -233,6 +263,7 @@ describe('Faculty overview', () => {
cy.get('[data-cy="FacultyStudentStatsTable"]').should('be.visible')
cy.get('[data-cy="FacultyStudentStatsTable"]').should('not.contain', '0 %')
})
it('User can view studentdata table with %', () => {
cy.get('[data-cy="FacultyStudentStatsTable"]').should('be.visible')
cy.get('[data-cy="HidePercentagesToggle"]').click()
@@ -245,8 +276,7 @@ describe('Faculty overview', () => {
cy.get('[data-cy="Graph-FacultyMastersProgress"]').should('be.visible')
cy.get('[data-cy="Graph-FacultyBachelorsProgress"]').should('be.visible')
})
// Following two tests just test that nothing goes broken after toggling
// No data for testing that data actual change as supposed
it('Graduations can be excluded', () => {
cy.get('[data-cy="FacultyStudentStatsTable"]').should('be.visible')
cy.get('[data-cy="StudentToggle"]').click()
+9 -9
View File
@@ -83,9 +83,9 @@ describe('Population Statistics with CS master', () => {
})
})
describe('Studyright Type filter', () => {
describe('Studyright type filter', () => {
it('is visible', () => {
cy.contains('Studyright Type')
cy.contains('Studyright type')
})
it('is set to all by default', () => {
@@ -129,7 +129,7 @@ describe('Population Statistics', () => {
})
})
it('Graduation filter works', { retries: 2 }, () => {
it('Graduation filter works', { retries: 3 }, () => {
runTestStepWithPreAndPostParts('GraduatedFromProgramme', () => {
const getCard = () => cy.cs('GraduatedFromProgramme-filter-card')
@@ -162,13 +162,13 @@ describe('Population Statistics', () => {
})
})
it('Credit filter works', () => {
it('Credit filter works', { retries: 3 }, () => {
runTestStepWithPreAndPostParts('CreditsEarned', () => {
testRangeFilter('CreditsEarned-filter-card', 50, 150, 118)
})
})
it('Age filter works', () => {
it('Age filter works', { retries: 3 }, () => {
cy.clock(MOCKED_DATE, ['Date'])
runTestStepWithPreAndPostParts('Age', () => {
testRangeFilter('Age-filter-card', 20, 40, 47)
@@ -241,7 +241,7 @@ describe('Population Statistics', () => {
})
})
it('"Reset All Filters" button works', () => {
it('"Reset All Filters" button works', { retries: 3 }, () => {
cy.cs('Gender-header').click()
cy.cs('genderFilter-dropdown').selectFromDropdown(0)
checkFilteringResult(42)
@@ -252,8 +252,8 @@ describe('Population Statistics', () => {
checkFilteringResult(defaultAmountOfStudents)
})
it('Studyright Type filter is not visible', () => {
cy.contains('Studyright Type').should('not.exist')
it('Studyright type filter is not visible', () => {
cy.contains('Studyright type').should('not.exist')
})
})
@@ -346,7 +346,7 @@ describe('Custom Population Statistics', () => {
cy.fixture('customPopulations').then(({ studentNumbersForCSStudentsSet1, studentNumbersForCSStudentsSet2 }) => {
const students = [...studentNumbersForCSStudentsSet1, ...studentNumbersForCSStudentsSet2]
runTestStepWithPreAndPostParts = createRunTestStepWithPreAndPostPartsFunction(students.length)
cy.cs('student-no-input').click().type(students.join('\n'))
cy.cs('student-number-input').click().type(students.join('\n'))
})
cy.cs('search-button').click()
})
+1 -1
View File
@@ -57,7 +57,7 @@ describe('When language center is opened', () => {
it('"Access denied" is shown', () => {
cy.init('/languagecenterview', 'norights')
cy.contains('Access denied')
cy.contains("You're currently not allowed to see this page.")
cy.contains("You don't currently have permission to view this page.")
cy.contains('Special populations').click()
cy.contains('Language center view').should('not.exist')
})
+21 -25
View File
@@ -1,7 +1,5 @@
/// <reference types="Cypress" />
// Now "Class statistics" in UI
const moment = require('moment')
const _ = require('lodash')
describe('Population Statistics tests', () => {
const pathToCSBach2017 =
@@ -91,7 +89,7 @@ describe('Population Statistics tests', () => {
cy.contains('Courses of class').click()
cy.get('Opiskelijan digitaidot - Kumpula').should('not.exist')
cy.get('[data-cy=curriculum-picker]').click()
cy.contains('2020 - 2022').click()
cy.contains('2020 - 2026').click()
cy.contains('Opiskelijan digitaidot - Kumpula')
})
@@ -102,11 +100,13 @@ describe('Population Statistics tests', () => {
.then($parentDiv => {
if (!$parentDiv.hasClass('active')) cy.contains('Students (170)').click()
})
cy.get('[data-cy=student-table-tabs]').contains('Tags').click()
cy.get('[data-cy=student-table-tabs]').within(() => {
cy.contains('Tags').click()
})
cy.contains('No tags defined. You can define them here.').find('a').click()
cy.contains('Tags').click()
cy.contains('Tietojenkäsittelytieteen kandiohjelma')
cy.contains('Create new tag')
cy.contains('Create a new tag')
})
// This test sometimes fails on headless mode. It seems that the click on the
@@ -132,21 +132,17 @@ describe('Population Statistics tests', () => {
cy.contains('Credit accumulation (for 170 students)')
})
it('Credit Statistics, Credits Gained tab works', () => {
it('Credit Statistics, Credits gained tab works', () => {
cy.selectStudyProgramme('Tietojenkäsittelytieteen kandiohjelma')
cy.contains('Credit statistics')
.parent()
.then($parentDiv => {
if (!$parentDiv.hasClass('active')) cy.contains('Credit statistics').click()
})
cy.contains('Credits Gained').click()
cy.contains('Credits gained').click()
cy.get("[data-cy='credits-gained-main-table']").should('contain', 'All students of the class')
const today = moment().endOf('month')
const months = Math.round(moment.duration(moment(today).diff(moment('2017-08-01'))).asMonths())
// Months are capped to goal time of the degree, 36 months is the goal time for bachelor's degree
const monthsForLimits = Math.min(36, months)
const limits = [1, ..._.range(1, 5).map(p => Math.ceil(monthsForLimits * ((p * 15) / 12))), null]
const ranges = _.range(1, limits.length).map(i => _.slice(limits, i - 1, i + 1))
const limits = [45, 90, 135, 180, null]
const ranges = limits.map((limit, i) => (i === 0 ? [1, limit] : [limits[i - 1], limit]))
cy.get('.credits-gained-table').should('contain', '(n = 170)')
@@ -165,14 +161,14 @@ describe('Population Statistics tests', () => {
}
cy.get("[data-cy='credits-gained-table-body'] td:nth-child(3)").then($els => {
const sum = [...$els].map($el => parseInt($el.innerText)).reduce((a, b) => a + b, 0)
const sum = [...$els].map($el => parseInt($el.innerText, 10)).reduce((a, b) => a + b, 0)
expect(sum).to.equal(170)
})
cy.get("[data-cy='credits-gained-table-Ei valintatapaa']").should('not.exist')
})
it('Credit Statistics, Credits Gained tab shows stats by admissions', () => {
it('Credit Statistics, Credits gained tab shows stats by admissions', () => {
cy.visit(pathToCSMaster2019)
cy.cs('filtered-students')
cy.contains('Credit statistics')
@@ -181,8 +177,7 @@ describe('Population Statistics tests', () => {
.then($parentDiv => {
if (!$parentDiv.hasClass('active')) cy.get("[data-cy='Credit statistics']").click()
})
cy.contains('Credits Gained').click()
cy.get('.credits-gained-divider').click()
cy.contains('Credits gained').click()
cy.get("[data-cy='credits-gained-table-Avoin väylä']").should('exist')
cy.get("[data-cy='credits-gained-table-Yhteispisteet']").should('exist')
cy.get("[data-cy='credits-gained-table-Muu']").should('exist')
@@ -198,8 +193,9 @@ describe('Population Statistics tests', () => {
})
cy.get("[data-cy='credit-stats-tab'] > .menu > :nth-child(2)").click()
cy.get("[data-cy='credit-stats-table-name-header']").should('contain', 'Statistic for n = 170 Students')
cy.get("[data-cy='credit-stats-mean']").should('contain', '114.74')
cy.get("[data-cy='credit-stats-population-size']").should('contain', 'n = 170')
cy.get("[data-cy='credit-stats-average']").should('contain', '114.74')
cy.get("[data-cy='credit-stats-median']").should('contain', '109.00')
cy.get("[data-cy='credit-stats-stdev']").should('contain', '65.53')
cy.get("[data-cy='credit-stats-min']").should('contain', '5')
cy.get("[data-cy='credit-stats-max']").should('contain', '314')
@@ -221,16 +217,16 @@ describe('Population Statistics tests', () => {
})
cy.contains(existing)
cy.contains(nonExisting).should('not.exist')
cy.contains('button', 'Check studentnumbers').click()
cy.contains('Check for studentnumbers')
cy.contains('button', 'Check student numbers').click()
cy.contains('Check for student numbers')
cy.get('textarea').type(existing).type('{enter}').type(nonExisting)
cy.contains('button', 'check students').click()
cy.contains('button', 'Check students').click()
cy.contains('#checkstudentsresults', 'Results').within(() => {
cy.contains('Student numbers in list and in oodi').click()
cy.contains('Student numbers in list and in Sisu').click()
cy.contains('#found', existing)
cy.contains('Student numbers in list but not in oodi').click()
cy.contains('Student numbers in list but not in Sisu').click()
cy.contains('#notfound', nonExisting)
cy.contains('Student numbers in oodi but not in list').click()
cy.contains('Student numbers in Sisu but not in list').click()
cy.contains('#notsearched', '010614509')
})
})
+13 -2
View File
@@ -39,7 +39,7 @@ describe('Students tests', () => {
cy.url().should('include', '/students')
cy.get('.prompt').type(student.studentnumber)
cy.contains('td a', student.studentnumber).click()
cy.contains('Tietojenkäsittelytieteen kandiohjelma (01.08.2017 - 31.07.2025')
cy.contains('Tietojenkäsittelytieteen kandiohjelma (01.08.2017–31.07.2025')
cy.contains(student.lastname).should('not.exist')
cy.contains(student.firstnames).should('not.exist')
@@ -64,6 +64,7 @@ describe('Students tests', () => {
cy.get('.prompt').type(student.studentnumber)
cy.contains('td a', student.studentnumber).click()
cy.contains('Introduction to Machine Learning (DATA11002)')
.parent()
.siblings()
.last()
.within(() => {
@@ -81,6 +82,14 @@ describe('Students tests', () => {
.and('include', 'https://sisu.helsinki.fi/tutor/role/staff/student/hy-hlo-84830887/basic/basic-info')
})
it('Bachelor Honours section is shown', () => {
cy.get('.prompt').type(student.studentnumber)
cy.contains('td a', student.studentnumber).click()
cy.contains('h4', 'Bachelor Honours')
cy.contains('.tag.label', 'Not qualified for Honours')
cy.contains('.tag.label', 'Has not graduated')
})
it('Searching with bad inputs doesnt yield results', () => {
cy.get('.prompt').type('SWAG LITTINEN')
cy.contains('Student number').should('not.exist')
@@ -92,7 +101,9 @@ describe('Students tests', () => {
it('Can jump to population page', () => {
cy.get('.prompt').type(student.studentnumber)
cy.contains('td a', student.studentnumber).click()
cy.get('i.level.up.alternate.icon').eq(0).click()
cy.contains('.ui.table', 'Completed').within(() => {
cy.get('i.level.up.alternate.icon').click()
})
cy.contains('Tietojenkäsittelytieteen kandiohjelma')
cy.contains('class size')
})
+10 -12
View File
@@ -15,7 +15,7 @@ describe('Study guidance group tests', () => {
cy.init('/studyguidancegroups')
cy.contains('Access denied')
cy.contains(
"You're currently not allowed to see this page. Please contant oodikone@helsinki.fi, if this is a mistake."
"You don't currently have permission to view this page. If you believe this is a mistake, please contact oodikone@helsinki.fi."
)
})
})
@@ -79,14 +79,7 @@ describe('Study guidance group tests', () => {
})
it('general tab of the students table has the correct columns', () => {
const firstRowHeadings = [
'Phone number',
'Student number',
'Credits',
'Start year at uni',
'Study programmes',
'Tags',
]
const firstRowHeadings = ['Student number', 'Credits', 'Start year at uni', 'Study programmes', 'Tags']
const secondRowHeadings = ['All', 'Since 1.1.1970']
cy.cs('Students (2)').click()
cy.get('[data-cy="student-table-tabs"] table thead tr').then($tr => {
@@ -137,7 +130,6 @@ describe('Study guidance group tests', () => {
it('general tab of the students table has the correct columns', () => {
const firstRowHeadings = [
'Phone number',
'Student number',
'Credits',
'Start of studyright',
@@ -146,7 +138,11 @@ describe('Study guidance group tests', () => {
'Graduation date',
'Start year at uni',
'Other programmes',
'Semesters present amount',
'Transferred from',
'Gender',
'Citizenship',
'Curriculum period',
'Latest attainment date',
'Tags',
]
const secondRowHeadings = ['All', 'HOPS', 'Since 1.8.2018']
@@ -154,7 +150,9 @@ describe('Study guidance group tests', () => {
cy.get('[data-cy="student-table-tabs"] table thead tr').then($tr => {
const firstRowTexts = Array.from($tr[0].children).map(elem => elem.innerText.replace('\n', ' '))
expect(firstRowTexts).to.deep.equal(firstRowHeadings)
const secondRowTexts = Array.from($tr[1].children).map(elem => elem.innerText)
const secondRowTexts = Array.from($tr[1].children)
.filter(elem => elem.style.display !== 'none')
.map(elem => elem.innerText)
expect(secondRowTexts).to.deep.equal(secondRowHeadings)
})
})
+77 -66
View File
@@ -23,7 +23,7 @@ const getEmptyYears = isAcademicYear => {
}
describe('Studyprogramme overview', () => {
/* Basic information overview -tests*/
/* Basic information overview -tests */
describe('Basic information -view works for basic user', () => {
beforeEach(() => {
cy.init('/study-programme')
@@ -42,24 +42,27 @@ describe('Studyprogramme overview', () => {
it('Basic information contains correct students', () => {
const years = getEmptyYears()
const tableContents = [
// [Year, Started, Graduated, Transferred Away, Transferred to]
...years.map(year => [year, 0, 0, 0, 0]),
[2021, 0, 0, 1, 0],
[2020, 10, 35, 2, 2],
[2019, 86, 17, 1, 1],
[2018, 161, 1, 0, 0],
[2017, 171, 0, 0, 0],
// [Year, Started studying, Accepted, Graduated, Transferred Away, Transferred to]
...years.map(year => [year, 0, 0, 0, 0, 0]),
[2021, 0, 0, 0, 1, 0],
[2020, 10, 10, 35, 2, 2],
[2019, 83, 86, 17, 1, 1],
[2018, 150, 161, 1, 0, 0],
[2017, 158, 171, 0, 0, 0],
]
cy.checkTableStats(tableContents, 'StudentsOfTheStudyprogramme')
})
it('Basic information contains correct credits', () => {
const years = getEmptyYears()
const tableContents = [
[2020, 4511, 4511, 0, 0, 167],
[2019, 7097, 7097, 0, 0, 349],
[2018, 5742, 5742, 0, 0, 272],
[2017, 1910, 1910, 0, 0, 388],
...years.map(year => [year, 0, 0]),
[2021, 0, 0, 0, 0, 0],
[2020, 4511, 4511, 0, 0, 406],
[2019, 7117, 7097, 0, 0, 434],
[2018, 5742, 5737, 0, 0, 150],
[2017, 1887, 1882, 0, 0, 186],
]
cy.checkTableStats(tableContents, 'CreditsProducedByTheStudyprogramme')
@@ -84,22 +87,24 @@ describe('Studyprogramme overview', () => {
cy.get('[data-cy=StudentToggle]').click()
const years = getEmptyYears()
const studentTableContents = [
// [Year, Started, Graduated]
...years.map(year => [year, 0, 0]),
[2021, 0, 0],
[2020, 10, 35],
[2019, 86, 17],
[2018, 161, 1],
[2017, 171, 0],
// [Year, Started studying, Accepted, Graduated]
...years.map(year => [year, 0, 0, 0]),
[2021, 0, 0, 0],
[2020, 10, 10, 35],
[2019, 83, 86, 17],
[2018, 150, 161, 1],
[2017, 158, 171, 0],
]
cy.checkTableStats(studentTableContents, 'StudentsOfTheStudyprogramme')
const creditTableContents = [
[2020, 4511, 4511, 0, 0, 167],
[2019, 7097, 7097, 0, 0, 349],
[2018, 5742, 5742, 0, 0, 272],
[2017, 1910, 1910, 0, 0, 388],
...years.map(year => [year, 0, 0]),
[2021, 0, 0, 0, 0, 0],
[2020, 4511, 4511, 0, 0, 406],
[2019, 7117, 7097, 0, 0, 434],
[2018, 5742, 5737, 0, 0, 150],
[2017, 1887, 1882, 0, 0, 186],
]
cy.checkTableStats(creditTableContents, 'CreditsProducedByTheStudyprogramme')
@@ -123,22 +128,23 @@ describe('Studyprogramme overview', () => {
const isAcademicYear = true
const years = getEmptyYears(isAcademicYear)
const studentTableContents = [
// [Year, Started, Graduated, Transferred away, Transferred to]
...years.map(year => [year, 0, 0, 0, 0]),
['2021 - 2022', 0, 0, 0, 0],
['2020 - 2021', 10, 6, 3, 2],
['2019 - 2020', 86, 38, 1, 0],
['2018 - 2019', 161, 8, 0, 1],
['2017 - 2018', 171, 1, 0, 0],
// [Year, Started studying, Accepted, Graduated, Transferred away, Transferred to]
...years.map(year => [year, 0, 0, 0, 0, 0]),
['2021 - 2022', 0, 0, 0, 0, 0],
['2020 - 2021', 10, 10, 6, 1, 2],
['2019 - 2020', 83, 86, 38, 3, 0],
['2018 - 2019', 150, 161, 8, 0, 1],
['2017 - 2018', 158, 171, 1, 0, 0],
]
cy.checkTableStats(studentTableContents, 'StudentsOfTheStudyprogramme')
const creditTableContents = [
// Credit table doesnt show (later) years without data
['2020 - 2021', 352, 352, 0, 0, 60],
['2019 - 2020', 6966, 6966, 0, 0, 193],
['2018 - 2019', 7777, 7777, 0, 0, 328],
['2017 - 2018', 4165, 4165, 0, 0, 344],
...years.map(year => [year, 0, 0]),
['2021 - 2022', 0, 0, 0, 0, 0],
['2020 - 2021', 352, 352, 0, 0, 296],
['2019 - 2020', 6966, 6966, 0, 0, 430],
['2018 - 2019', 7797, 7777, 0, 0, 259],
['2017 - 2018', 4142, 4132, 0, 0, 191],
]
cy.checkTableStats(creditTableContents, 'CreditsProducedByTheStudyprogramme')
@@ -147,15 +153,17 @@ describe('Studyprogramme overview', () => {
it('Basic information graphs render', () => {
cy.get('[data-cy=Graph-StudentsOfTheStudyprogramme')
.should('contain', 'Started')
.should('contain', 'Started studying')
.should('contain', 'Accepted')
.should('contain', 'Graduated')
.should('contain', 'Transferred away')
.should('contain', 'Transferred to')
cy.get('[data-cy=Graph-CreditsProducedByTheStudyprogramme')
.should('contain', 'Degree students')
.should('contain', 'Transferred')
.should('contain', 388)
.should('contain', 7097)
.should('contain', 434)
cy.get('[data-cy=Graph-GraduatedAndThesisWritersOfTheProgramme')
.should('contain', 'Graduated students')
@@ -170,11 +178,11 @@ describe('Studyprogramme overview', () => {
cy.get('[data-cy=GraduationTimeToggle]').click()
cy.get('[data-cy=graduation-times-graphBachelor]').within(() => {
cy.contains('Graduation year')
cy.contains('2019')
cy.contains('17 graduated').trigger('mouseover')
cy.contains('study time: 23 months')
cy.contains('17 graduated on time')
cy.contains('0 graduated max year overtime')
cy.contains('2020')
cy.contains('35 graduated').trigger('mouseover')
cy.contains('median study time: 34 months')
cy.contains('30 graduated on time')
cy.contains('5 graduated max year overtime')
})
cy.get('[data-cy=Graph-ProgrammesBeforeOrAfter')
@@ -200,9 +208,9 @@ describe('Studyprogramme overview', () => {
cy.contains('Graduation year')
cy.contains('2020')
cy.contains('24 graduated').trigger('mouseover')
cy.contains('study time: 22 months')
cy.contains('20 graduated on time')
cy.contains('4 graduated max year overtime')
cy.contains('study time: 22.5 months')
cy.contains('19 graduated on time')
cy.contains('5 graduated max year overtime')
})
cy.get('[data-cy=graduation-times-graphBachelor]').within(() => {
@@ -215,7 +223,7 @@ describe('Studyprogramme overview', () => {
})
})
/* Studytrack overview -tests*/
/* Studytrack overview -tests */
describe('Studytrack overview works for basic user', () => {
beforeEach(() => {
cy.init('/study-programme')
@@ -232,27 +240,28 @@ describe('Studyprogramme overview', () => {
it('Students of the studyprogramme are shown correctly', () => {
const tableContents = [
// [Year, All, Started studying, Currently enrolled, Absent, Inactive, Graduated, Men, Women, other/unknown Finnish, other]
// [Year, All, Started studying, Present, Absent, Inactive, Graduated, Men, Women, Other/Unknown, Finland, Other]
['2020 - 2021', 12, 10, 0, 0, 12, 0, 10, 2, 0, 12, 0],
['2019 - 2020', 86, 86, 0, 0, 85, 1, 65, 21, 0, 86, 0],
['2018 - 2019', 162, 161, 0, 0, 151, 11, 118, 44, 0, 161, 1],
['2017 - 2018', 171, 171, 0, 0, 129, 42, 135, 36, 0, 166, 5],
['Total', 431, 428, 0, 0, 377, 54, 328, 103, 0, 425, 6],
['2019 - 2020', 86, 83, 0, 0, 85, 1, 65, 21, 0, 86, 0],
['2018 - 2019', 162, 150, 0, 0, 151, 11, 118, 44, 0, 161, 1],
['2017 - 2018', 171, 158, 0, 0, 130, 41, 135, 36, 0, 166, 5],
['Total', 431, 401, 0, 0, 378, 53, 328, 103, 0, 425, 6],
]
cy.checkTableStats(tableContents, 'StudytrackOverview')
})
it('Student progress data is shown correctly', () => {
const years = getEmptyYears(true)
const tableContents = [
['2023 - 2024', 0, 0, 0, 0, 0, 0, 0, 0],
['2022 - 2023', 0, 0, 0, 0, 0, 0, 0, 0],
// [Year, All, < 30 credits, 30–60 credits, 60–90 credits, 90–120 credits, 120–150 credits, 150–180 credits, ≥ 180 credits]
...years.map(year => [year, 0, 0, 0, 0, 0, 0, 0, 0]),
['2021 - 2022', 0, 0, 0, 0, 0, 0, 0, 0],
['2020 - 2021', 12, 12, 0, 0, 0, 0, 0, 0],
['2019 - 2020', 86, 26, 34, 21, 5, 0, 0, 0],
['2018 - 2019', 162, 10, 27, 47, 36, 26, 12, 4],
['2018 - 2019', 162, 10, 28, 47, 35, 26, 12, 4],
['2017 - 2018', 171, 20, 21, 26, 22, 22, 33, 27],
['Total', 431, 68, 82, 94, 63, 48, 45, 31],
['Total', 431, 68, 83, 94, 62, 48, 45, 31],
]
cy.checkTableStats(tableContents, 'StudytrackProgress')
@@ -270,15 +279,15 @@ describe('Studyprogramme overview', () => {
cy.get('[data-cy=graduation-times-graphBachelor]').within(() => {
cy.contains('Start year')
cy.contains('2019 - 2020')
cy.contains('42 graduated').trigger('mouseover')
cy.contains('study time: 31.5 months')
cy.contains('39 graduated on time')
cy.contains('2017 - 2018')
cy.contains('41 graduated').trigger('mouseover')
cy.contains('study time: 31 months')
cy.contains('36 graduated on time')
})
})
})
/* Programme courses -tests*/
/* Programme courses -tests */
describe('Programme courses works for basic user', () => {
beforeEach(() => {
cy.init('/study-programme')
@@ -347,7 +356,7 @@ describe('Studyprogramme overview', () => {
})
})
/* Tag-tests*/
/* Tag-tests */
describe('Basic information -view works for basic user', () => {
beforeEach(() => {
cy.init('/study-programme')
@@ -359,7 +368,7 @@ describe('Studyprogramme overview', () => {
const name = `tag-${new Date().getTime()}`
cy.get('.tagNameSelectInput > .ui > input').type(name)
cy.get('.yearSelectInput').type('2018')
cy.contains('Create new tag').click()
cy.contains('Create a new tag').click()
cy.contains(name)
cy.contains('2018')
deleteTag(name)
@@ -371,7 +380,7 @@ describe('Studyprogramme overview', () => {
cy.get('.yearSelectInput').type('2018')
cy.get('.ui > label').click()
cy.contains('Create new tag').click()
cy.contains('Create a new tag').click()
cy.contains(name)
deleteTag(name)
})
@@ -382,16 +391,18 @@ describe('Studyprogramme overview', () => {
const student = '010113437'
cy.get('.tagNameSelectInput > .ui > input').type(name)
cy.get('.yearSelectInput').type('2018')
cy.contains('Create new tag').click()
cy.contains('Create a new tag').click()
cy.contains(name)
cy.contains('Add tags to students').click()
cy.contains('Add a tag to students').click()
cy.get('.form > .field > .dropdown').click().get('.ui > input.search').type(name).click()
cy.get('.form > .field > .dropdown > .visible').contains(name).click()
cy.get('textarea').type('010113437')
cy.get('.positive').click()
cy.contains('Add tags').click()
cy.contains('Successfully added tags to students.')
cy.contains('Students').click()
cy.get('.prompt').type(student)
+13 -7
View File
@@ -11,7 +11,7 @@ describe('Teachers page tests', () => {
it('Check Statistics', () => {
cy.get(':nth-child(1) > .ui > .search').click()
cy.contains('Autumn 2020').click()
cy.contains('Syksy 2020').click()
cy.cs('course-providers').click()
cy.contains('Tietojenkäsittelytieteen kandiohjelma').click()
cy.cs('course-providers').children('.icon').click()
@@ -25,15 +25,21 @@ describe('Teachers page tests', () => {
cy.url().should('include', '/teachers')
cy.get('.borderless > :nth-child(3)').click()
cy.get('.prompt').type(teacher1.split()[0])
cy.contains(teacher1)
cy.contains('td', teacher1)
})
it('Can check teacher page', () => {
cy.url().should('include', '/teachers')
cy.get('.borderless > :nth-child(3)').click()
cy.get('.prompt').type(teacher1.split()[0])
cy.contains('td', teacher1).click()
cy.contains('Aineopintojen harjoitustyö: Tietokantasovellus')
cy.visit('/teachers/hy-hlo-51367956')
cy.contains('Landgraf Leo')
cy.get('.ok-sortable-table tbody tr')
.first()
.within(() => {
cy.contains('td:nth-child(1)', 'TKT20011')
cy.contains('td:nth-child(2)', 'Aineopintojen harjoitustyö: Tietokantasovellus')
cy.contains('td:nth-child(3)', '96')
cy.contains('td:nth-child(4)', '0')
cy.contains('td:nth-child(5)', '88.89%')
})
})
it('Check leaderboad works', () => {
+2
View File
@@ -13,6 +13,8 @@
// https://on.cypress.io/configuration
// ***********************************************************
// eslint-disable-next-line import/no-extraneous-dependencies
require('@cypress/code-coverage/support')
require('./commands')
// This error is benign and seems to be only present in Cypress
+3 -3
View File
@@ -44,7 +44,7 @@ services:
<<: *defaults
command: >
sh -c 'redis-server --appendonly yes && redis-cli flushall'
image: redis:6.2.13
image: redis:6.2.14
ports:
- 6379:6379
@@ -81,7 +81,7 @@ services:
jami-db:
<<: *defaults
image: postgres:13.2
image: postgres:15.7
environment:
- PGDATA=/data
- POSTGRES_PASSWORD=postgres
@@ -161,6 +161,6 @@ services:
<<: *defaults
command: '-cid sis-updater-nats -m 8222 -p 4222 --max_channels 1000 --max_age 2h --hb_fail_count 2 --hb_timeout 10s --hb_interval 10s --auth dev --file_slice_max_bytes 0 --file_slice_max_age 60s --max_msgs 0 -store file -dir datastore'
container_name: sis-updater-nats
image: nats-streaming:0.16.2
image: nats-streaming:0.25.6
profiles:
- updater
+185
View File
@@ -0,0 +1,185 @@
x-defaults: &defaults
restart: unless-stopped
x-build_defaults: &build_defaults
dockerfile: dev.Dockerfile
services:
adminer:
<<: *defaults
container_name: adminer
environment:
ADMINER_DESIGN: pepa-linha
image: adminer:4.8.1
ports:
- 5050:8080
volumes:
- ./adminer-plugins:/var/www/html/plugins-enabled
backend:
<<: *defaults
build:
<<: *build_defaults
context: services/backend
depends_on:
- kone-db
- redis
- sis-db
- user-db
env_file:
- .env
environment:
DB_URL_KONE: postgres://postgres@kone-db:5432/kone-db
DB_URL_USER: postgres://postgres@user-db:5432/user-db
FRONT_URL: http://localhost:3000
REDIS: redis
SECRET_TOKEN: dev
SIS_DB_URL: postgres://postgres@sis-db:5432/sis-db
SIS_UPDATER_URL: http://sis-updater-scheduler:8082
IMPORTER_DB_API_URL: 'https://localhost:3005'
JAMI_URL: 'http://jami:3003/'
SERVICE_PROVIDER: 'Fd'
SIS_HOST: ${SIS_HOST}
SIS_GRAPHQL_APPLICATION_ACCOUNT: ${SIS_GRAPHQL_APPLICATION_ACCOUNT}
SIS_GRAPHQL_APPLICATION_KEY: ${SIS_GRAPHQL_APPLICATION_KEY}
ports:
- 8080:8080
volumes:
- ./environments/ha:/opt/app-root/src/src/environment
- ./services/backend/src:/opt/app-root/src/src
frontend:
<<: *defaults
build:
<<: *build_defaults
context: services/frontend
container_name: frontend
ports:
- 3000:3000
environment:
REACT_APP_SERVICE_PROVIDER: 'Fd'
volumes:
- ./services/frontend/src/:/opt/app-root/src/src
kone-db:
<<: *defaults
container_name: kone-db
environment:
PGDATA: /data
POSTGRES_DB: kone-db
POSTGRES_HOST_AUTH_METHOD: trust
image: postgres:15.7
ports:
- 12349:5432
volumes:
- kone-db-data:/data
redis:
<<: *defaults
command: 'redis-server --appendonly yes'
container_name: redis
image: redis:6.2.14
ports:
- '6379:6379'
volumes:
- redis-data:/data
sis-db:
<<: *defaults
container_name: sis-db
environment:
PGDATA: /data
POSTGRES_DB: sis-db
POSTGRES_HOST_AUTH_METHOD: trust
image: postgres:15.7
volumes:
- sis-db-data:/data
shm_size: 2gb
ports:
- 12345:5432
sis-updater-nats:
<<: *defaults
command: '-cid sis-updater-nats -m 8222 -p 4222 --max_channels 1000 --max_age 2h --hb_fail_count 2 --hb_timeout 10s --hb_interval 10s --auth dev --file_slice_max_bytes 0 --file_slice_max_age 60s --max_msgs 0 -store file -dir datastore'
container_name: sis-updater-nats
image: nats-streaming:0.25.6
sis-updater-scheduler:
<<: *defaults
build:
<<: *build_defaults
context: updater/sis-updater-scheduler
container_name: sis-updater-scheduler
extra_hosts:
- 'host.docker.internal:host-gateway'
depends_on:
- redis
- sis-updater-nats
environment:
REDIS_URI: //redis:6379
SECRET_TOKEN: dev
SIS_IMPORTER_HOST: ${SIS_IMPORTER_DB_HOST:-host.docker.internal}
SIS_IMPORTER_PORT: ${SIS_IMPORTER_DB_PORT:-15234}
SIS_IMPORTER_DATABASE: importer-db
SIS_IMPORTER_PASSWORD: dev
SIS_IMPORTER_USER: dev
SIS_NATS_TOKEN: dev
SIS_NATS_URI: sis-updater-nats://sis-updater-nats:4222
ports:
- 8082:8082
volumes:
- ./updater/sis-updater-scheduler/:/opt/app-root/src
sis-updater-worker:
<<: *defaults
deploy:
replicas: 2
mode: replicated
build:
<<: *build_defaults
context: updater/sis-updater-worker
depends_on:
- redis
- sis-db
- sis-updater-nats
extra_hosts:
- 'host.docker.internal:host-gateway'
environment:
DB_URL: postgres://postgres@sis-db:5432/sis-db
REDIS_URI: //redis:6379
SIS_IMPORTER_HOST: ${SIS_IMPORTER_DB_HOST:-host.docker.internal}
SIS_IMPORTER_PORT: ${SIS_IMPORTER_DB_PORT:-15234}
SIS_IMPORTER_DATABASE: importer-db
SIS_IMPORTER_PASSWORD: dev
SIS_IMPORTER_USER: dev
SIS_PASSWORD: postgres
SIS_NATS_TOKEN: dev
SIS_NATS_URI: sis-updater-nats://sis-updater-nats:4222
ROOT_ORG_ID: ${ROOT_ORG_ID}
volumes:
- ./updater/sis-updater-worker/:/opt/app-root/src
user-db:
<<: *defaults
container_name: user-db
environment:
PGDATA: /data
POSTGRES_DB: user-db
POSTGRES_HOST_AUTH_METHOD: trust
image: postgres:15.7
volumes:
- user-db-data:/data
ports:
- 12347:5432
volumes:
kone-db-data:
redis-data:
sis-db-data:
user-db-data:
networks:
default:
name: oodikone
importer:
name: importer_network
external: true
+5
View File
@@ -0,0 +1,5 @@
services:
frontend:
volumes:
- frontend-nodemod:/opt/app-root/src/node_modules
- ./services/frontend/instrumented:/opt/app-root/src/src
+7 -6
View File
@@ -1,5 +1,3 @@
version: '2.1'
x-defaults: &defaults
restart: unless-stopped
@@ -12,7 +10,7 @@ services:
container_name: adminer
environment:
ADMINER_DESIGN: pepa-linha
image: adminer:4.8.0
image: adminer:4.8.1
ports:
- 5050:8080
volumes:
@@ -30,6 +28,7 @@ services:
- user-db
env_file:
- .env
tty: true
environment:
DB_URL_KONE: postgres://postgres@kone-db:5432/kone-db
DB_URL_USER: postgres://postgres@user-db:5432/user-db
@@ -75,7 +74,7 @@ services:
<<: *defaults
command: 'redis-server --appendonly yes'
container_name: redis
image: redis:6.2.13
image: redis:6.2.14
ports:
- '6379:6379'
volumes:
@@ -106,7 +105,7 @@ services:
<<: *defaults
command: '-cid sis-updater-nats -m 8222 -p 4222 --max_channels 1000 --max_age 2h --hb_fail_count 2 --hb_timeout 10s --hb_interval 10s --auth dev --file_slice_max_bytes 0 --file_slice_max_age 60s --max_msgs 0 -store file -dir datastore'
container_name: sis-updater-nats
image: nats-streaming:0.16.2
image: nats-streaming:0.25.6
profiles:
- updater
@@ -175,6 +174,8 @@ services:
jami:
<<: *defaults
image: quay.io/toska/jami:production
env_file:
- .env
environment:
- npm_config_cache=/tmp
- PORT=3003
@@ -186,7 +187,7 @@ services:
jami-db:
<<: *defaults
image: postgres:13.2
image: postgres:15.7
environment:
- PGDATA=/data
- POSTGRES_PASSWORD=postgres
+3
View File
@@ -0,0 +1,3 @@
# Documentation
Oodikone public documentation. For internal documentation, see Toska GitLab.
+3 -3
View File
@@ -25,7 +25,7 @@ Basic rule of thumb is that for the master/licentiate programme I used names `co
All things listed below should work automatically, if new combinations are done.
- Credits produced byt the studyprogramme
- Credits produced by the studyprogramme
- credits are computed for both programmes separately
- Average graduation times
- For bachelor + master/licentiate studyright the time is the whole study time starting from bachelor
@@ -50,7 +50,7 @@ All things listed below should work automatically, if new combinations are done.
- Possibility to add criteria for whole bachelor-master study time
- For eläinlääkis this criteria is saved by bachelor programme code. Other cases may need other approaches.
In eläinklääkis this done by adding the criteria for 6 years -> the whole study time criteria is saved with the bachelor programme code. That is, same criteria is found, if bachelor or combined programme view is shown. This approach might need extra thinking for different programmes.
In eläinlääkis this done by adding the criteria for 6 years -> the whole study time criteria is saved with the bachelor programme code. That is, same criteria is found, if bachelor or combined programme view is shown. This approach might need extra thinking for different programmes.
- Show own tables for both programmes
- To fetch data **needs manual work** here `services/backend/src/services/studyprogrammeHelpers.js` in the constant `combinedStudyprogrammes`.
@@ -93,4 +93,4 @@ All things listed below should work automatically, if new combinations are done.
- Backend: student data is fetched by bachelor study programme code in `/v3/populationstatisticsbystudentnumbers`. Separation from code 'KHxx_xxx+MHxx_xxx' is done in backend.
- Frontend: things are done in the same way as with class stats.
- **Need manual work**: `./oodikone/services/frontend/src/redux/elementdetails.js` add combined programme codes (both bachelor and master) to `combinedProgrammeCodes` and modify `combinedOptions` list accordinly in `useFilterAndFormattedElementDetails()` function.
- **Need manual work**: `./oodikone/services/frontend/src/redux/elementdetails.js` add combined programme codes (both bachelor and master) to `combinedProgrammeCodes` and modify `combinedOptions` list accordingly in `useFilterAndFormattedElementDetails()` function.
+37
View File
@@ -0,0 +1,37 @@
# Databases
Oodikone uses three separate databases, each for different purposes. This document contains a simplified overview of each database and the relations between models.
Use Adminer or refer to the actual database for a detailed view of each model and their attributes.
## sis-db
The `sis-db` database contains information originating from Sisu.
_To be documented._
## kone-db
The `kone-db` database contains information used in various features of Oodikone. This functionality is native to Oodikone and not necessarily directly related to Sisu.
```mermaid
erDiagram
custom_population_searches
excluded_courses
open_uni_population_searches
progress_criteria
study_guidance_group_tags
study_programme_pins
tag ||--o{ tag_student : "belongs to"
tag
tag_student
```
## user-db
The `user-db` database contains information about users of Oodikone.
```mermaid
erDiagram
users
```

Before

Width:  |  Height:  |  Size: 165 KiB

After

Width:  |  Height:  |  Size: 165 KiB

Before

Width:  |  Height:  |  Size: 106 KiB

After

Width:  |  Height:  |  Size: 106 KiB

Before

Width:  |  Height:  |  Size: 72 KiB

After

Width:  |  Height:  |  Size: 72 KiB

+82 -25
View File
@@ -1,48 +1,105 @@
# Mystery numbers
# Numeric types
Sis data uses some numeric classifiers that are not self-explanatory and (most) previously needed to be deciphered from existing code.
Some mystery numbers are gathered here for convenience. Feel free to add anything that could be useful. Remember to use the spelling used in code to enable project wide search.
Data used in Oodikone contains some numeric types (or _magic numbers_) that are not self-explanatory. The values of the numeric types are gathered here for convenience and quick reference.
## extentcode
## Extent code
(from **studyright**)
Appears in model Studyright (db: `studyright`) as _extentcode_ (db: `extentcode`) and in model SISStudyRight (db: `sis_study_rights`) as _extentCode_ (db: `extent_code`). Values are defined in the database table `studyright_extents`.
These are actually defined in db table studyright_extents. Tells studyright level or type, eg. bachelor's degree or non-degree studies.
| value | meaning |
| ----: | :-------------------------------------------------- |
| 1 | Bachelor's degree |
| 2 | Master's degree |
| 3 | Licentiate |
| 4 | Doctor |
| 5 | Bachelor's and Master's degree |
| 6 | Continuing education |
| 7 | Exchange studies |
| 9 | Open University studies |
| 13 | Non-degree pedagogical studies for teachers |
| 14 | Contract training |
| 16 | Studies for secondary school students |
| 18 | Specialisation studies |
| 22 | Non-degree programme for special education teachers |
| 23 | Specialist training in medicine and dentistry |
| 31 | Summer and winter school |
| 34 | Exchange studies (postgraduate studies) |
| 99 | Non-Degree studies |
## prioritycode
## Priority code
(from **studyright**)
> [!WARNING]
> Obsolete, to be deprecated
1: Primary
Appears in model Studyright (db: `studyright`) as _prioritycode_ (db: `prioritycode`).
2: Secondary
| value | meaning | notes |
| ----: | :-------- | :------------------------------------------------------------------------------------------ |
| 1 | Primary | |
| 2 | Secondary | |
| 5 | Rescinded | seemingly not in use anymore |
| 6 | Option | Ba+Ma students can add a master programme to their study plan before graduating as bachelor |
| 30 | Graduated | |
5: Rescinded (Seemingly not in use anymore)
## Type
6: Option (Bachelor+master studyright students can add a master programme to their study plan before graduation in bachelor programme: marked as option in Oodikone)
> [!WARNING]
> Obsolete, to be deprecated
30: Graduated
Appears in model ElementDetails (db: `element_details`) as _type_ (db: `type`).
## type
| value | meaning |
| ----: | :----------------------------------------------- |
| 20 | study programme |
| 30 | module, studytrack or kokonaisuus e.g. neurology |
(from **element_details**)
## Phase
20: A study programme
Appears in model SISStudyRightElement (db: `sis_study_right_elements`) as _phase_ (db: `phase`).
30: Module/Studytrack/kokonaisuus? Eg. Neurology
In Finland it is common for new students to be awarded the study right to both a bachelor's and a master's programme when they are admitted to the university. In Oodikone these two-phase study rights are marked with the [extent code](#extent-code) 5. In the study right elements of these study rights, phase 2 marks the second phase of the study right.
## enrollmenttype
For example: Student is awarded the study right in the bachelor's programme in computer science with the extent code 5. The study right element for study right in the bachelor's programme is marked with phase 1. After graduating from the bachelor's programme, the student continues their studies in the master's programme in computer science. The new study right element for the study right in the master's programme is marked with phase 2.
(from **semester_enrollments**)
All study right elements for other study rights (extent code other than 5) are marked with phase 1.
1: Present
The level of the programme (bachelor's, master's etc.) of the study right can be directly checked from degreeProgrammeType (db: `degree_programme_type`) in model SISStudyRightElement (db: `sis_study_right_elements`).
2: Absent
| value | meaning |
| ----: | :------- |
| 1 | any |
| 2 | master's |
3: Inactive (neither 1 or 2 has been declared)
## Enrollment type
## credittypecode
Appears in model SemesterEnrollment (db: `semester_enrollments`) as _enrollmenttype_ (db: `enrollmenttype`).
(from **credit**)
| value | meaning | notes |
| ----: | :------- | :------------------------------- |
| 1 | Present | |
| 2 | Absent | |
| 3 | Inactive | neither 1 or 2 has been declared |
Defined in credit_types db table. Completed/Improved/Transferred/Failed
## Credit type code
Appears in model Credit (db: `credit`) as _credittypecode_ (db: `credittypecode`). Values are defined in the database table `credit_types`.
Completed/Improved/Transferred/Failed
| value | meaning |
| ----: | :--------------- |
| 4 | Completed |
| 7 | Improved (grade) |
| 9 | Transferred |
| 10 | Failed |
## Gender code
Appears in model Student (db: `student`) as _gender_code_ (db: `gender_code`).
| value | meaning |
| ----: | :------ |
| 0 | Unknown |
| 1 | Male |
| 2 | Female |
| 3 | Other |
+50
View File
@@ -0,0 +1,50 @@
# Resources
A collection of useful resources and documentation.
## AI tools
- [ChatGPT](https://chatgpt.com)
- [CurreChat](https://curre.helsinki.fi/chat)
- [GitHub Copilot](https://github.com/features/copilot)
- Free for students!
- [Microsoft Copilot](https://copilot.microsoft.com)
## Code style and maintainability
- [CodeClimate documentation](https://docs.codeclimate.com/docs)
- [Advanced configuration](https://docs.codeclimate.com/docs/advanced-configuration)
- [ESLint documentation](https://eslint.org/docs/v8.x)
- [Prettier documentation](https://prettier.io/docs/en)
## Database
- [Postgres documentation](https://www.postgresql.org/docs/15/index.html)
- [Sequelize documentation](https://sequelize.org/docs/v6/)
## GitHub
- [GitHub documentation](https://docs.github.com/en)
- [GitHub Actions](https://docs.github.com/en/actions)
- [GitHub Education](https://github.com/education/students)
- Free benefits for students!
- [Mermaid.js documentation](https://mermaid.js.org/intro/syntax-reference.html)
## TypeScript
- [TypeScript documentation](https://www.typescriptlang.org/docs)
- [`tsconfig` reference](https://www.typescriptlang.org/tsconfig)
- [TypeScript instructions for Sequelize](https://sequelize.org/docs/v6/other-topics/typescript)
- [`sequelize-typescript` instructions](https://github.com/sequelize/sequelize-typescript?tab=readme-ov-file#readme)
## User interface
- [Semantic UI React documentation](https://react.semantic-ui.com)
## Visual Studio Code
_Todo: add relevant plugins_
## Web technologies
- [MDN Web Docs](https://developer.mozilla.org/en-US/)
+3
View File
@@ -0,0 +1,3 @@
# Tietosuoja
Oodikoneessa noudatetaan Helsingin yliopiston [yleistä linjausta](https://www.helsinki.fi/fi/tutustu-meihin/tietosuoja#opiskelijoiden-henkil-tietojen-k-sittely--title) opiskelijoiden henkilötietojen käsittelystä.
+7
View File
@@ -0,0 +1,7 @@
/* eslint-disable import/no-extraneous-dependencies */
const { parserPlugins } = require('@istanbuljs/schema').defaults.nyc
module.exports = {
cache: false,
parserPlugins: parserPlugins.concat('typescript', 'jsx'),
}
+5311 -1098
View File
File diff suppressed because it is too large Load Diff
+22 -10
View File
@@ -3,14 +3,18 @@
"description": "An application for analyzing university data.",
"scripts": {
"cypress": "cypress",
"concurrently": "concurrently",
"cypress:open": "cypress open",
"cypress:run": "cypress run --browser chrome",
"instrument": "./scripts/instrument.sh",
"eslint": "eslint",
"lint:all": "eslint --ext .js,.jsx,.ts,.tsx services/ updater/ --report-unused-disable-directives",
"stylelint": "stylelint",
"actionlint": "node-actionlint",
"prettier": "prettier",
"cli": "./cli.sh",
"oodikone": "./run.sh oodikone anon up --detach",
"oodikone:real": "./run.sh oodikone real up --detach",
"oodikone:test": "./run.sh oodikone test up --detach",
"updater": "./run.sh updater anon up --detach",
"updater:real": "./run.sh updater real up --detach",
"both": "./run.sh both anon up --detach",
@@ -18,8 +22,11 @@
"docker:down": "./run.sh both anon down --remove-orphans; ./run.sh both real down --remove-orphans",
"testupdater": "docker-compose --file docker-compose.ci.yml up --detach --no-recreate sis-updater-worker && SCHEDULE_IMMEDIATE=weekly EXIT_AFTER_IMMEDIATES=yes docker-compose --file docker-compose.ci.yml run sis-updater-scheduler npm start",
"flushredis": "docker exec -it redis redis-cli flushall",
"prepare": "husky install",
"rapodiff": "docker exec oodikone_backend_1 node /opt/app-root/src/src/rapodiff/rapodiff.js"
"prepare": "husky",
"rapodiff": "docker exec oodikone_backend_1 node /opt/app-root/src/src/rapodiff/rapodiff.js",
"install:local": "npm i && cd services/frontend && npm i && cd ../backend && npm i && cd ../../updater/sis-updater-scheduler && npm i && cd ../sis-updater-worker && npm i && cd ../..",
"install:docker": "docker exec frontend npm i && docker exec oodikone_backend_1 npm i && docker exec sis-updater-scheduler npm i && docker exec oodikone_sis-updater-worker_1 npm i",
"install:both": "npm run install:local && npm run install:docker"
},
"repository": {
"type": "git",
@@ -31,27 +38,32 @@
},
"homepage": "https://github.com/UniversityOfHelsinkiCS/oodikone#readme",
"devDependencies": {
"concurrently": "^7.4.0",
"@cypress/code-coverage": "^3.12.39",
"@istanbuljs/schema": "^0.1.3",
"@typescript-eslint/eslint-plugin": "^7.16.1",
"@typescript-eslint/parser": "^7.16.1",
"cypress": "^13.2.0",
"eslint": "^8.56.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-config-airbnb-typescript": "^18.0.0",
"eslint-config-prettier": "^9.1.0",
"eslint-import-resolver-custom-alias": "^1.3.2",
"eslint-plugin-cypress": "^2.15.1",
"eslint-plugin-cypress": "^3.0.0",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-jsx-a11y": "^6.8.0",
"eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-prettier": "^5.2.1",
"eslint-plugin-react": "^7.33.2",
"eslint-plugin-react-hooks": "^4.6.0",
"husky": "^8.0.1",
"lint-staged": "^13.0.3",
"husky": "^9.0.0",
"lint-staged": "^15.0.0",
"node-actionlint": "^1.2.2",
"prettier": "3.2.5",
"nyc": "^17.0.0",
"prettier": "3.3.3",
"stylelint": "^16.2.1",
"stylelint-config-standard": "^36.0.0"
},
"dependencies": {
"lodash": "^4.17.21",
"moment": "^2.29.4"
"moment": "^2.30.1"
}
}
+22
View File
@@ -0,0 +1,22 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": ["config:recommended"],
"packageRules": [
{
"groupName": "all non-major dependencies",
"groupSlug": "all-minor-patch",
"matchPackagePatterns": ["*"],
"matchUpdateTypes": ["minor", "patch"]
},
{
"matchDatasources": ["docker"],
"matchPackageNames": ["node"],
"versionCompatibility": "^(?<version>[^-]+)(?<compatibility>-.*)?$",
"versioning": "node"
}
],
"rebaseWhen": "never",
"vulnerabilityAlerts": {
"labels": ["security"]
}
}
+4 -1
View File
@@ -47,7 +47,7 @@ parse_params() {
compose_command=${args[*]:1}
else
version=${args[1]}
[[ "$version" != "anon" && "$version" != "real" ]] && usage && \
[[ "$version" != "anon" && "$version" != "real" && "$version" != "test" ]] && usage && \
die "Wrong version $version"
compose_command=${args[*]:2}
fi
@@ -70,6 +70,9 @@ parse_env() {
if [[ "$version" == "real" ]]; then
env="--file docker-compose.yml --file docker-compose.real.yml"
fi
if [[ "$version" == "test" ]]; then
env="--file docker-compose.yml --file docker-compose.test.yml"
fi
return 0
}
-1
View File
@@ -204,7 +204,6 @@ set_up_oodikone_from_scratch() {
infomsg "Cleaning up docker setup and node_modules from possible previous installations"
local compose_down_args="--remove-orphans --volumes --rmi all"
"$PROJECT_ROOT"/run.sh both down "$compose_down_args" || infomsg "Cleaning errored, but will continue"
docker-compose --file "$PROJECT_ROOT"/docker-compose.test.yml "$compose_down_args" || infomsg "Cleaning errored, but will continue"
docker-compose --file "$PROJECT_ROOT"/docker-compose.ci.yml "$compose_down_args" || infomsg "Cleaning errored, but will continue"
for folder in "${folders_to_set_up[@]}"; do
cd "$folder" || die "Couldn't change directory to folder $folder"
+30
View File
@@ -0,0 +1,30 @@
#!/usr/bin/env bash
# This script is used for instrumenting the frontend code
# Counters are added for calculating the code coverage
# Instrumented code is used for generating code coverage reports
# Ensure the script exits if any command fails
set -euo pipefail
# Define the directories
SOURCE_DIR="services/frontend/src"
INSTRU_DIR="services/frontend/instrumented"
# Print status
echo -n "Instrumenting frontend code... "
# Create the instrumented directory if it does not exist
mkdir -p $INSTRU_DIR
# Instrument the code
nyc instrument --all --compact=false $SOURCE_DIR $INSTRU_DIR
# Copy remaining files without overwriting instrumented files
#
# Images, CSS and other static files are not instrumended
# but they are still needed to run the application
rsync -av --quiet --ignore-existing $SOURCE_DIR/ $INSTRU_DIR/
# Print status
echo "Done!"
+37 -5
View File
@@ -1,4 +1,35 @@
FROM registry.access.redhat.com/ubi9/nodejs-18-minimal
FROM registry.access.redhat.com/ubi9/nodejs-20-minimal as build
ENV TZ="Europe/Helsinki"
WORKDIR /opt/app-root/src
ENV NODE_ENV=production
ENV NODE_OPTIONS=--max-old-space-size=4096
ARG BASE_PATH
ENV PUBLIC_URL=$BASE_PATH
ARG STAGING
ENV REACT_APP_STAGING=$STAGING
ARG SENTRY_ENVIRONMENT
ENV SENTRY_ENVIRONMENT=$SENTRY_ENVIRONMENT
ARG SENTRY_RELEASE
ENV SENTRY_RELEASE=$SENTRY_RELEASE
COPY ./package*.json ./
RUN npm ci --include=dev
COPY . .
RUN npm run build
FROM registry.access.redhat.com/ubi9/nodejs-20-minimal
ENV TZ="Europe/Helsinki"
@@ -21,8 +52,9 @@ ENV SENTRY_ENVIRONMENT=$SENTRY_ENVIRONMENT
ARG SENTRY_RELEASE
ENV SENTRY_RELEASE=$SENTRY_RELEASE
COPY ./package* ./
RUN npm ci --omit-dev
COPY . .
COPY --from=build /opt/app-root/src/package*.json ./
COPY --from=build /opt/app-root/src/dist ./dist
CMD ["node", "index.js"]
RUN npm ci
CMD ["node", "dist/index.js"]
Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

-141
View File
@@ -1,141 +0,0 @@
// Map programme codes to "letter indentifier"
const codes = {
KH10_001: 'tuk',
MH10_001: 'tum',
KH20_001: 'on',
MH20_001: 'otm',
MH20_002: 'ibl',
MH20_003: 'ggl',
KH30_001: 'psyk',
MH30_004: 'psym',
KH30_002: 'logk',
MH30_005: 'logm',
MH30_001: 'll',
MH30_002: 'tmed',
MH30_003: 'hll',
MH30_006: 'terv',
KH40_001: 'filk',
KH40_002: 'ttk',
KH40_003: 'kik',
KH40_004: 'kok',
KH40_005: 'kuka',
KH40_006: 'hisk',
MH40_001: 'ttm',
MH40_002: 'kim',
MH40_003: 'eng',
MH40_004: 'rus',
MH40_005: 'lingdig',
MH40_006: 'tra',
MH40_007: 'suku',
MH40_008: 'nor',
MH40_009: 'kir',
MH40_010: 'kuma',
MH40_011: 'ice',
MH40_012: 'alku',
MH40_014: 'spt',
MH40_015: 'hism',
KH50_001: 'mat',
KH50_002: 'fys',
KH50_003: 'kemk',
KH50_004: 'mfkk',
KH50_005: 'tkt',
KH50_006: 'geok',
KH50_007: 'maa',
KH50_008: 'bsc',
MH50_001: 'mast',
MH50_002: 'lsi',
MH50_003: 'tcm',
MH50_004: 'paras',
MH50_005: 'matres',
MH50_006: 'atm',
MH50_007: 'kem',
MH50_008: 'mfkm',
MH50_009: 'csm',
MH50_010: 'data',
MH50_011: 'geom',
MH50_012: 'geog',
MH50_013: 'usp',
KH55_001: 'farm',
MH55_001: 'prov',
MH55_002: 'mpharm',
KH57_001: 'bio',
KH57_002: 'mole',
KH57_003: 'env',
MH57_001: 'eeb',
MH57_002: 'ips',
MH57_003: 'gmb',
MH57_004: 'neuro',
MH57_005: 'ecgs',
KH60_001: 'eduk',
MH60_001: 'edum',
MH60_002: 'ce',
KH70_001: 'pvk',
KH70_002: 'yk',
KH70_003: 'sosk',
KH70_004: 'ecok',
MH70_001: 'film',
MH70_002: 'pvm',
MH70_003: 'gpc',
MH70_004: 'ym',
MH70_005: 'cos',
MH70_006: 'ens',
MH70_007: 'msv',
MH70_008: 'sosm',
MH70_009: 'econ',
MH70_011: 'sote',
KH74_001: 'ksv',
KH80_001: 'maatk',
KH80_002: 'metsak',
KH80_003: 'etk',
KH80_004: 'yet',
MH80_001: 'agri',
MH80_002: 'agere',
MH80_003: 'for',
MH80_004: 'food',
MH80_005: 'hnfb',
MH80_006: 'ekm',
MH80_007: 'mmb',
MH80_008: 'emplant',
KH90_001: 'elk',
MH90_001: 'ell',
T920101: 'dptheol',
T920102: 'dplaw',
T920111: 'philartsoc',
T920103: 'dphistcult',
T920104: 'dplang',
T920105: 'sky',
T920106: 'dpsocs',
T920107: 'pyam',
T920108: 'dpe',
T920109: 'seduce',
T920110: 'clic',
T921101: 'dpbm',
T921102: 'klto',
T921103: 'docpop',
T921104: 'findos',
T921105: 'dpdr',
T921106: 'ils',
T921107: 'bandm',
T921108: 'cvm',
T921109: 'dphub',
T922101: 'luova',
T922102: 'dpps',
T922103: 'denvi',
T922104: 'agforee',
T922105: 'mbdp',
T922106: 'foodhealth',
T923101: 'papu',
T923102: 'geodoc',
T923103: 'atm-dp',
T923104: 'chems',
T923105: 'domast',
T923106: 'matrena',
T923107: 'docs',
// manually added programs with no IAM, either abolished, or special co-operation programmes
MH50_014: 'ech',
MH40_013: 'mkk',
MH70_010: 'imes',
}
module.exports = { codes }
+2 -2
View File
@@ -1,4 +1,4 @@
FROM node:18-alpine
FROM node:20-alpine
ENV TZ="Europe/Helsinki"
@@ -13,4 +13,4 @@ COPY ./package* ./
RUN npm ci
COPY . .
CMD ["node_modules/.bin/nodemon", "index.js"]
CMD ["node_modules/.bin/tsx", "watch", "--clear-screen=false", "index.js"]
+3
View File
@@ -4,3 +4,6 @@ const logger = require('./src/util/logger')
process.on('unhandledRejection', reason => {
logger.error({ message: 'unhandledRejection: ', meta: reason })
})
process.on('SIGTERM', () => process.exit())
process.on('SIGINT', () => process.exit())
+3057 -429
View File
File diff suppressed because it is too large Load Diff
+18 -9
View File
@@ -2,36 +2,45 @@
"name": "backend",
"private": true,
"scripts": {
"start": "node --max_old_space_size=4096 index.js",
"dev": "nodemon --max_old_space_size=4096 index.js",
"build": "tsc",
"rapodiff": "node /opt/app-root/src/src/rapodiff.js"
},
"dependencies": {
"@sentry/node": "^5.30.0",
"@sentry/tracing": "^6.18.2",
"axios": "^0.21.4",
"axios": "^0.28.1",
"bluebird": "^3.7.2",
"bullmq": "^4.14.2",
"compression": "^1.7.4",
"cors": "^2.8.5",
"cron": "^1.8.2",
"express": "^4.18.2",
"express": "^4.19.2",
"express-async-errors": "^3.1.1",
"lodash": "^4.17.21",
"lru-cache": "^5.1.1",
"moment": "^2.29.1",
"lru-cache": "^10.2.2",
"moment": "^2.30.1",
"moment-timezone": "^0.5.37",
"morgan": "^1.10.0",
"papaparse": "^5.4.1",
"pg": "^8.8.0",
"pg": "^8.11.5",
"redis": "^3.1.2",
"sequelize": "^6.24.0",
"reflect-metadata": "^0.2.2",
"sequelize": "^6.37.3",
"sequelize-typescript": "^2.1.6",
"umzug": "^2.3.0",
"unfuck-utf8-headers-middleware": "^1.0.1",
"winston": "^3.8.2",
"winston-gelf-transporter": "^1.0.2"
},
"devDependencies": {
"nodemon": "^3.0.3"
"@types/express": "^4.17.21",
"@types/lodash": "^4.17.6",
"@types/morgan": "^1.9.9",
"@types/node": "^20.14.2",
"@types/umzug": "^2.3.7",
"@types/validator": "^13.12.0",
"tsx": "^4.16.2",
"typescript": "^5.5.3"
},
"overrides": {
"winston-gelf-transporter": {
+6 -5
View File
@@ -1,9 +1,10 @@
require('express-async-errors')
const express = require('express')
const { baseUrl, backendPort } = require('./conf-backend')
const routes = require('./routes')
const { startCron } = require('./events')
const { baseUrl, backendPort } = require('./config')
const { initializeDatabaseConnection, dbConnections } = require('./database/connection')
const { startCron } = require('./events')
const routes = require('./routes')
const logger = require('./util/logger')
require('./worker/worker')
@@ -30,7 +31,7 @@ initializeDatabaseConnection()
})
})
})
.catch(e => {
.catch(error => {
process.exitCode = 1
logger.error(e)
logger.error(error)
})
@@ -6,6 +6,7 @@ const isProduction = !isStaging && process.env.NODE_ENV === 'production'
// Sentry
const sentryRelease = process.env.SENTRY_RELEASE || ''
const sentryEnvironment = process.env.SENTRY_ENVIRONMENT || ''
const sentryDSN = process.env.SENTRY_DSN || ''
const runningInCI = process.env.CI === 'true'
// IAM group
@@ -23,17 +24,27 @@ const jamiUrl = process.env.JAMI_URL || ''
const importerUrl = process.env.IMPORTER_DB_API_URL || ''
const importerToken = process.env.IMPORTER_DB_API_TOKEN || ''
// Sisu
const sisUrl = process.env.SIS_HOST
const sisGrapqlAppAccount = process.env.SIS_GRAPHQL_APPLICATION_ACCOUNT
const sisGrapqlAppKey = process.env.SIS_GRAPHQL_APPLICATION_KEY
// Networking: Urls & ports
const baseUrl = isDev ? '/api' : ''
const frontUrl = process.env.FRONT_URL
const backendPort = 8080
// System run in whose environment
const serviceProvider = process.env.SERVICE_PROVIDER || 'Toska'
// Optional logout-url configuration
const configLogoutUrl = serviceProvider === 'Toska' ? undefined : process.env.LOGOUT_URL
// Other stuff
const DB_URL_KONE = process.env.DB_URL_KONE
const DB_URL_USER = process.env.DB_URL_USER
const { DB_URL_KONE, DB_URL_USER, SECRET_TOKEN, SIS_DB_URL, SIS_UPDATER_URL, CRYPT_KEY } = process.env
let DB_MAX_CONNECTIONS = parseInt(process.env.DB_MAX_CONNECTIONS, 10)
if (isNaN(DB_MAX_CONNECTIONS)) {
if (Number.isNaN(DB_MAX_CONNECTIONS)) {
DB_MAX_CONNECTIONS = 5 // sequelize's default
}
let DB_MAX_CRON_CONNECTIONS = DB_MAX_CONNECTIONS - 5
@@ -42,16 +53,12 @@ if (DB_MAX_CRON_CONNECTIONS < 1) {
}
const redis = process.env.REDIS
const SECRET_TOKEN = process.env.SECRET_TOKEN
const DB_SCHEMA_KONE = process.env.DB_SCHEMA_KONE || 'public'
const SIS_UPDATER_URL = process.env.SIS_UPDATER_URL
const KONE_PASSWORD = process.env.KONE_PASSWORD || 'postgres'
const USER_PASSWORD = process.env.USER_PASSWORD || 'postgres'
const SIS_PASSWORD = process.env.SIS_PASSWORD || 'postgres'
const CRYPT_KEY = process.env.CRYPT_KEY
module.exports = {
DB_URL_USER,
CRYPT_KEY,
@@ -65,10 +72,12 @@ module.exports = {
USER_PASSWORD,
SIS_PASSWORD,
requiredGroup,
SIS_DB_URL,
SIS_UPDATER_URL,
runningInCI,
sentryRelease,
sentryEnvironment,
sentryDSN,
isProduction,
pateToken,
jamiUrl,
@@ -78,4 +87,10 @@ module.exports = {
importerUrl,
importerToken,
isDev,
isStaging,
serviceProvider,
configLogoutUrl,
sisUrl,
sisGrapqlAppAccount,
sisGrapqlAppKey,
}
@@ -0,0 +1,4 @@
// Linter was not having any of this so neeeded to add resolveJsonModule:true to tsconfig
// export const { facultyCodes, ignoredFacultyCodes, magicFacultyCode } = require('../environment/organizationConfig.json')
export { facultyCodes, ignoredFacultyCodes, magicFacultyCode } from '../environment/organizationConfig.json'
@@ -0,0 +1,138 @@
// Map programme codes to "letter indentifier"
export const programmeCodes = {
KH10_001: 'TUK',
MH10_001: 'TUM',
KH20_001: 'ON',
MH20_001: 'OTM',
MH20_002: 'IBL',
MH20_003: 'GGL',
KH30_001: 'PSYKK',
KH30_002: 'LOGOK',
KH30_003: 'SPK',
MH30_001: 'LL',
MH30_002: 'TMED',
MH30_003: 'HLL',
MH30_004: 'PSYK',
MH30_005: 'LOGO',
MH30_006: 'TERV',
KH40_001: 'FILK',
KH40_002: 'TTK',
KH40_003: 'KIK',
KH40_004: 'KOK',
KH40_005: 'KUKA',
KH40_006: 'HISK',
MH40_001: 'TTM',
MH40_002: 'KIM',
MH40_003: 'ENG',
MH40_004: 'MAREEES',
MH40_005: 'LingDig',
MH40_006: 'TRA',
MH40_007: 'SUKU',
MH40_008: 'NOR',
MH40_009: 'KIR',
MH40_010: 'KUMA',
MH40_011: 'ICE',
MH40_012: 'ALKU',
MH40_014: 'SPT',
MH40_015: 'HISM',
KH50_001: 'MAT',
KH50_002: 'FYS',
KH50_003: 'KEMK',
KH50_004: 'MFKK',
KH50_005: 'TKT',
KH50_006: 'GEOK',
KH50_007: 'MAA',
KH50_008: 'BSC',
MH50_001: 'MAST',
MH50_002: 'LSI',
MH50_003: 'TCM',
MH50_004: 'PARAS',
MH50_005: 'MATRES',
MH50_006: 'ATM',
MH50_007: 'KEM',
MH50_008: 'MFKM',
MH50_009: 'CSM',
MH50_010: 'DATA',
MH50_011: 'GEOM',
MH50_012: 'GEOG',
MH50_013: 'USP',
MH50_014: 'EnCHiL',
KH55_001: 'FARM',
MH55_001: 'PROV',
MH55_002: 'MPHARM',
KH57_001: 'BIO',
KH57_002: 'MOLE',
KH57_003: 'ENV',
MH57_001: 'EEB',
MH57_002: 'IPS',
MH57_003: 'GMB',
MH57_004: 'NEURO',
MH57_005: 'ECGS',
KH60_001: 'EDUK',
MH60_001: 'EDUM',
MH60_002: 'CE',
KH70_001: 'PVK',
KH70_002: 'YK',
KH70_003: 'SOSK',
KH70_004: 'ECOK',
MH70_001: 'FILM',
MH70_002: 'PVM',
MH70_003: 'GPC',
MH70_004: 'YM',
MH70_005: 'COS',
MH70_006: 'ENS',
MH70_007: 'MSV',
MH70_008: 'SOSM',
MH70_009: 'ECON',
MH70_010: 'IMESS',
MH70_011: 'SOTE',
KH74_001: 'KSV',
KH80_001: 'MAATK',
KH80_002: 'METSAK',
KH80_003: 'ETK',
KH80_004: 'YET',
MH80_001: 'AGRI',
MH80_002: 'AGERE',
MH80_003: 'FOR',
MH80_004: 'FOOD',
MH80_005: 'HNFB',
MH80_006: 'EKM',
MH80_007: 'MMB',
MH80_008: 'emPlant',
KH90_001: 'ELK',
MH90_001: 'ELL',
T920101: 'DPTHEOL',
T920102: 'DPLAW',
T920103: 'DPHISTCULT',
T920104: 'DPLANG',
T920105: 'SKY',
T920106: 'DPSOCS',
T920107: 'PYAM',
T920108: 'DPE',
T920109: 'SEDUCE',
T920110: 'CLIC',
T920111: 'PHILARTSOC',
T921101: 'DPBM',
T921102: 'KLTO',
T921103: 'DocPop',
T921104: 'FINDOS',
T921105: 'DPDR',
T921106: 'ILS',
T921107: 'BM',
T921108: 'CVM',
T921109: 'DPHUB',
T922101: 'LUOVA',
T922102: 'DPPS',
T922103: 'DENVI',
T922104: 'AGFOREE',
T922105: 'MBDP',
T922106: 'FoodHealth',
T923101: 'PAPU',
T923102: 'GeoDoc',
T923103: 'ATM-DP',
T923104: 'CHEMS',
T923105: 'DOMAST',
T923106: 'MATRENA',
T923107: 'DOCS',
} as const
+10
View File
@@ -0,0 +1,10 @@
export const roles = [
'admin',
'courseStatistics',
'facultyStatistics',
'fullSisuAccess',
'katselmusViewer',
'openUniSearch',
'studyGuidanceGroups',
'teachers',
] as const
-114
View File
@@ -1,114 +0,0 @@
const Sequelize = require('sequelize')
const EventEmitter = require('events')
const Umzug = require('umzug')
const conf = require('../conf-backend')
const { SIS_DB_URL } = process.env
const logger = require('../util/logger')
class DbConnection extends EventEmitter {
constructor() {
super()
this.RETRY_ATTEMPTS = 15
this.established = false
this.sequelize = new Sequelize(SIS_DB_URL, {
dialect: 'postgres',
pool: {
max: 25,
min: 0,
acquire: 30000,
idle: 300000000,
},
logging: false,
password: conf.SIS_PASSWORD,
})
}
async connect(attempt = 1) {
try {
await this.sequelize.authenticate()
this.emit('connect')
this.established = true
} catch (e) {
if (attempt > this.RETRY_ATTEMPTS) {
this.emit('error', e)
return
}
logger.error({ message: `Sis database connection failed! Attempt ${attempt}/${this.RETRY_ATTEMPTS}`, meta: e })
setTimeout(() => this.connect(attempt + 1), 1000 * attempt)
}
}
}
// Old-style kone + user db connections
const sequelizeKone = new Sequelize(conf.DB_URL_KONE, {
schema: conf.DB_SCHEMA_KONE,
searchPath: conf.DB_SCHEMA_KONE,
logging: false,
password: conf.KONE_PASSWORD,
})
sequelizeKone.query(`SET SESSION search_path to ${conf.DB_SCHEMA_KONE}`)
const sequelizeUser = new Sequelize(conf.DB_URL_USER, {
logging: false,
password: conf.USER_PASSWORD,
})
const initializeDatabaseConnection = async () => {
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))
const rounds = 60
for (const [seq, dbName] of [
[sequelizeKone, 'kone-db'],
[sequelizeUser, 'user-db'],
]) {
logger.info(`Connecting to ${dbName}...`)
for (let round = 1; round <= rounds; round++) {
try {
await seq.authenticate()
break
} catch (error) {
if (round === rounds) {
logger.error(`${dbName} database connection failed!`)
throw error
}
await sleep(1000)
}
}
logger.info(`${dbName} database connection established`)
const schema = dbName === 'kone-db' ? conf.DB_SCHEMA_KONE : undefined
const migrationsFolder = dbName === 'kone-db' ? 'migrations_kone' : 'migrations_user'
const migrator = new Umzug({
storage: 'sequelize',
storageOptions: {
sequelize: seq,
tableName: 'migrations',
schema,
},
migrations: {
params: [seq.getQueryInterface(), Sequelize],
path: `${process.cwd()}/src/database/${migrationsFolder}`,
pattern: /\.js$/,
schema,
},
})
try {
const migrations = await migrator.up()
logger.info({ message: `${dbName} migrations up to date: `, meta: migrations.map(m => m.file) })
} catch (error) {
logger.error({ message: `${dbName} migrations failed`, meta: error })
throw error
}
}
}
const dbConnections = new DbConnection()
module.exports = {
dbConnections,
sequelizeKone,
sequelizeUser,
initializeDatabaseConnection,
}
+187
View File
@@ -0,0 +1,187 @@
import EventEmitter from 'events'
import { Sequelize } from 'sequelize-typescript'
import Umzug from 'umzug'
import conf from '../config'
import {
Course,
CourseProvider,
CourseType,
Credit,
CreditTeacher,
CreditType,
ElementDetail,
Enrollment,
Organization,
ProgrammeModule,
ProgrammeModuleChild,
Semester,
SemesterEnrollment,
SISStudyRight,
SISStudyRightElement,
Student,
Studyplan,
Studyright,
StudyrightElement,
StudyrightExtent,
Teacher,
Transfer,
} from '../models'
import {
CustomPopulationSearch,
ExcludedCourse,
OpenUniPopulationSearch,
ProgressCriteria,
StudyGuidanceGroupTag,
StudyProgrammePin,
Tag,
TagStudent,
} from '../models/kone'
import { User } from '../models/user'
import logger from '../util/logger'
class DbConnection extends EventEmitter {
sequelize: Sequelize
RETRY_ATTEMPTS: number
established: boolean
constructor() {
super()
this.RETRY_ATTEMPTS = 15
this.established = false
this.sequelize = new Sequelize(conf.SIS_DB_URL!, {
dialect: 'postgres',
pool: {
max: 25,
min: 0,
acquire: 30000,
idle: 300000000,
},
logging: false,
password: conf.SIS_PASSWORD,
models: [
Course,
CourseProvider,
CourseType,
Credit,
CreditTeacher,
CreditType,
ElementDetail,
Enrollment,
Organization,
ProgrammeModule,
ProgrammeModuleChild,
Semester,
SemesterEnrollment,
SISStudyRight,
SISStudyRightElement,
Student,
Studyplan,
Studyright,
StudyrightElement,
StudyrightExtent,
Teacher,
Transfer,
],
})
}
async connect(attempt = 1) {
try {
await this.sequelize.authenticate()
this.emit('connect')
this.established = true
} catch (error) {
if (attempt > this.RETRY_ATTEMPTS) {
this.emit('error', error)
return
}
logger.error({
message: `Sis database connection failed! Attempt ${attempt}/${this.RETRY_ATTEMPTS}`,
meta: error,
})
setTimeout(() => this.connect(attempt + 1), 1000 * attempt)
}
}
}
// Old-style kone + user db connections
const sequelizeKone = new Sequelize(conf.DB_URL_KONE!, {
schema: conf.DB_SCHEMA_KONE,
logging: false,
password: conf.KONE_PASSWORD,
models: [
CustomPopulationSearch,
ExcludedCourse,
OpenUniPopulationSearch,
ProgressCriteria,
StudyGuidanceGroupTag,
StudyProgrammePin,
Tag,
TagStudent,
],
})
sequelizeKone.query(`SET SESSION search_path to ${conf.DB_SCHEMA_KONE}`)
const sequelizeUser = new Sequelize(conf.DB_URL_USER!, {
logging: false,
password: conf.USER_PASSWORD,
models: [User],
})
const initializeDatabaseConnection = async () => {
const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms))
const rounds = 60
for (const [seq, dbName] of [
[sequelizeKone, 'kone-db'],
[sequelizeUser, 'user-db'],
] as const) {
logger.info(`Connecting to ${dbName}...`)
for (let round = 1; round <= rounds; round++) {
try {
await seq.authenticate()
break
} catch (error) {
if (round === rounds) {
logger.error(`${dbName} database connection failed!`)
throw error
}
await sleep(1000)
}
}
logger.info(`${dbName} database connection established`)
const schema = dbName === 'kone-db' ? conf.DB_SCHEMA_KONE : undefined
const migrationsFolder = dbName === 'kone-db' ? 'migrations_kone' : 'migrations_user'
const migrator = new Umzug({
storage: 'sequelize',
storageOptions: {
sequelize: seq,
tableName: 'migrations',
schema,
},
migrations: {
params: [seq.getQueryInterface(), Sequelize],
path: `${process.cwd()}${conf.isProduction || conf.isStaging ? '/dist' : ''}/src/database/${migrationsFolder}`,
pattern: /\.js$/,
},
})
try {
const migrations = await migrator.up()
logger.info({ message: `${dbName} migrations up to date: `, meta: migrations.map(migration => migration.file) })
} catch (error) {
logger.error({ message: `${dbName} migrations failed`, meta: error })
throw error
}
}
}
const dbConnections = new DbConnection()
export { dbConnections, sequelizeKone, sequelizeUser, initializeDatabaseConnection }
@@ -1,13 +1,12 @@
module.exports = {
up: async queryInterface => {
return queryInterface.sequelize.transaction(async transaction => {
await queryInterface.sequelize.query('ALTER TABLE tag_student DROP CONSTRAINT "tag_student_tag_id_fkey"', {
transaction,
})
await queryInterface.removeConstraint('tag_student', 'tag_student_tag_id_fkey', { transaction })
await queryInterface.sequelize.query('DELETE FROM tag_student WHERE tag_id IS NULL', { transaction })
await queryInterface.removeConstraint('tag', 'tag_tag_id_key', { transaction })
await queryInterface.addConstraint('tag', ['tag_id'], {
await queryInterface.addConstraint('tag', {
type: 'primary key',
fields: ['tag_id'],
transaction,
})
await queryInterface.sequelize.query(
@@ -15,8 +14,9 @@ module.exports = {
{ transaction }
)
await queryInterface.removeColumn('tag_student', 'id', { transaction })
await queryInterface.addConstraint('tag_student', ['studentnumber', 'tag_id'], {
await queryInterface.addConstraint('tag_student', {
type: 'primary key',
fields: ['studentnumber', 'tag_id'],
transaction,
})
})
@@ -0,0 +1,18 @@
const Sequelize = require('sequelize')
module.exports = {
up: async queryInterface => {
await queryInterface.createTable('study_programme_pins', {
user_id: {
primaryKey: true,
type: Sequelize.INTEGER,
},
study_programmes: {
type: Sequelize.ARRAY(Sequelize.STRING),
},
})
},
down: async queryInterface => {
await queryInterface.dropTable('study_programme_pins')
},
}
@@ -29,7 +29,6 @@ CREATE EXTENSION IF NOT EXISTS plpgsql WITH SCHEMA pg_catalog;
-- Name: EXTENSION plpgsql; Type: COMMENT; Schema: -; Owner:
--
COMMENT ON EXTENSION plpgsql IS 'PL/pgSQL procedural language';
SET search_path = public, pg_catalog;
@@ -52,7 +51,6 @@ CREATE TABLE access_groups (
);
ALTER TABLE access_groups OWNER TO postgres;
--
-- Name: access_groups_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres
@@ -66,7 +64,6 @@ CREATE SEQUENCE access_groups_id_seq
CACHE 1;
ALTER TABLE access_groups_id_seq OWNER TO postgres;
--
-- Name: access_groups_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres
@@ -87,7 +84,6 @@ CREATE TABLE affiliations (
);
ALTER TABLE affiliations OWNER TO postgres;
--
-- Name: affiliations_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres
@@ -101,7 +97,6 @@ CREATE SEQUENCE affiliations_id_seq
CACHE 1;
ALTER TABLE affiliations_id_seq OWNER TO postgres;
--
-- Name: affiliations_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres
@@ -122,7 +117,6 @@ CREATE TABLE faculty_programmes (
);
ALTER TABLE faculty_programmes OWNER TO postgres;
--
-- Name: hibernate_sequence; Type: SEQUENCE; Schema: public; Owner: postgres
@@ -136,7 +130,6 @@ CREATE SEQUENCE hibernate_sequence
CACHE 1;
ALTER TABLE hibernate_sequence OWNER TO postgres;
--
-- Name: hy_groups; Type: TABLE; Schema: public; Owner: postgres
@@ -150,7 +143,6 @@ CREATE TABLE hy_groups (
);
ALTER TABLE hy_groups OWNER TO postgres;
--
-- Name: hy_groups_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres
@@ -164,7 +156,6 @@ CREATE SEQUENCE hy_groups_id_seq
CACHE 1;
ALTER TABLE hy_groups_id_seq OWNER TO postgres;
--
-- Name: hy_groups_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres
@@ -183,7 +174,6 @@ CREATE TABLE sequence (
);
ALTER TABLE sequence OWNER TO postgres;
--
-- Name: user_accessgroup; Type: TABLE; Schema: public; Owner: postgres
@@ -198,7 +188,6 @@ CREATE TABLE user_accessgroup (
);
ALTER TABLE user_accessgroup OWNER TO postgres;
--
-- Name: user_accessgroup_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres
@@ -212,7 +201,6 @@ CREATE SEQUENCE user_accessgroup_id_seq
CACHE 1;
ALTER TABLE user_accessgroup_id_seq OWNER TO postgres;
--
-- Name: user_accessgroup_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres
@@ -234,7 +222,6 @@ CREATE TABLE user_affiliation (
);
ALTER TABLE user_affiliation OWNER TO postgres;
--
-- Name: user_affiliation_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres
@@ -248,7 +235,6 @@ CREATE SEQUENCE user_affiliation_id_seq
CACHE 1;
ALTER TABLE user_affiliation_id_seq OWNER TO postgres;
--
-- Name: user_affiliation_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres
@@ -269,7 +255,6 @@ CREATE TABLE user_elementdetails (
);
ALTER TABLE user_elementdetails OWNER TO postgres;
--
-- Name: user_faculties; Type: TABLE; Schema: public; Owner: postgres
@@ -283,7 +268,6 @@ CREATE TABLE user_faculties (
);
ALTER TABLE user_faculties OWNER TO postgres;
--
-- Name: user_hy_group; Type: TABLE; Schema: public; Owner: postgres
@@ -298,7 +282,6 @@ CREATE TABLE user_hy_group (
);
ALTER TABLE user_hy_group OWNER TO postgres;
--
-- Name: user_hy_group_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres
@@ -312,7 +295,6 @@ CREATE SEQUENCE user_hy_group_id_seq
CACHE 1;
ALTER TABLE user_hy_group_id_seq OWNER TO postgres;
--
-- Name: user_hy_group_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres
@@ -332,7 +314,6 @@ CREATE TABLE user_unit (
);
ALTER TABLE user_unit OWNER TO postgres;
--
-- Name: user_unit_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres
@@ -346,7 +327,6 @@ CREATE SEQUENCE user_unit_id_seq
CACHE 1;
ALTER TABLE user_unit_id_seq OWNER TO postgres;
--
-- Name: user_unit_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres
@@ -368,7 +348,6 @@ CREATE TABLE users (
);
ALTER TABLE users OWNER TO postgres;
--
-- Name: users_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres
@@ -382,7 +361,6 @@ CREATE SEQUENCE users_id_seq
CACHE 1;
ALTER TABLE users_id_seq OWNER TO postgres;
--
-- Name: users_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres
@@ -0,0 +1,41 @@
const { ARRAY, STRING } = require('sequelize')
module.exports = {
up: async queryInterface => {
await queryInterface.addColumn('users', 'roles', {
type: ARRAY(STRING),
allowNull: false,
defaultValue: [],
})
await queryInterface.sequelize.query(`
UPDATE users
SET roles = COALESCE(subquery.roles, '{}')
FROM (
SELECT uag."userId" AS "userId", ARRAY_AGG(ag.group_code) AS roles
FROM user_accessgroup uag
JOIN access_groups ag ON uag."accessGroupId" = ag.id
GROUP BY uag."userId"
) AS subquery
WHERE users.id = subquery."userId"
`)
await queryInterface.addColumn('users', 'programme_rights', {
type: ARRAY(STRING),
allowNull: false,
defaultValue: [],
})
await queryInterface.sequelize.query(`
UPDATE users
SET programme_rights = subquery.programme_rights
FROM (
SELECT "userId", ARRAY_AGG("elementDetailCode") AS programme_rights
FROM "user_elementdetails"
GROUP BY "userId"
) AS subquery
WHERE users.id = subquery."userId"
`)
},
down: async queryInterface => {
await queryInterface.removeColumn('users', 'roles')
await queryInterface.removeColumn('users', 'programme_rights')
},
}
@@ -0,0 +1,6 @@
module.exports = {
up: async queryInterface => {
await queryInterface.dropTable('user_faculties')
},
down: async () => {},
}
@@ -0,0 +1,6 @@
module.exports = {
up: async queryInterface => {
await queryInterface.dropTable('user_elementdetails')
},
down: async () => {},
}
@@ -0,0 +1,6 @@
module.exports = {
up: async queryInterface => {
await queryInterface.dropTable('user_accessgroup')
},
down: async () => {},
}
@@ -0,0 +1,6 @@
module.exports = {
up: async queryInterface => {
await queryInterface.dropTable('access_groups')
},
down: async () => {},
}
@@ -0,0 +1,6 @@
module.exports = {
up: async queryInterface => {
await queryInterface.removeColumn('users', 'iam_groups')
},
down: async () => {},
}
@@ -0,0 +1,6 @@
module.exports = {
up: async queryInterface => {
await queryInterface.dropTable('"Sessions"')
},
down: async () => {},
}
@@ -0,0 +1,23 @@
{
"facultyCodes": [
"H10",
"H20",
"H30",
"H40",
"H50",
"H55",
"H57",
"H60",
"H70",
"H74",
"H80",
"H90",
"H92",
"H930",
"H99",
"Y",
"Y01"
],
"magicFacultyCode": "H50",
"ignoredFacultyCodes": ["Y", "H99", "Y01", "H92", "H930"]
}
+54 -45
View File
@@ -1,17 +1,21 @@
const { CronJob } = require('cron')
const { refreshAssociationsInRedis } = require('./services/studyrights')
const { getAllProgrammes } = require('./services/studyrights')
const { updateBasicView, updateStudytrackView } = require('./services/studyprogramme/studyprogrammeUpdates')
const { findAndSaveTeachers } = require('./services/topteachers')
const { faculties } = require('./services/organisations')
const { combinedStudyprogrammes } = require('./services/studyprogramme/studyprogrammeHelpers')
const { isProduction, runningInCI } = require('./config')
const { getFaculties } = require('./services/faculty/facultyHelpers')
const { updateFacultyOverview, updateFacultyProgressOverview } = require('./services/faculty/facultyUpdates')
const { isProduction, runningInCI } = require('./conf-backend')
const { getCurrentSemester } = require('./services/semesters')
const logger = require('./util/logger')
const { getAssociations } = require('./services/studyrights')
const { redisClient } = require('./services/redis')
const { computeLanguageCenterData, LANGUAGE_CENTER_REDIS_KEY } = require('./services/languageCenterData')
const {
findStudentsCloseToGraduation,
CLOSE_TO_GRADUATION_REDIS_KEY,
} = require('./services/populations/closeToGraduation')
const { redisClient } = require('./services/redis')
const { getCurrentSemester } = require('./services/semesters')
const { combinedStudyprogrammes, isRelevantProgramme } = require('./services/studyProgramme/studyProgrammeHelpers')
const { updateBasicView, updateStudytrackView } = require('./services/studyProgramme/studyProgrammeUpdates')
const { getAssociations, getProgrammesFromStudyRights, refreshAssociationsInRedis } = require('./services/studyrights')
const { findAndSaveTeachers } = require('./services/topteachers')
const { deleteOutdatedUsers } = require('./services/userService')
const logger = require('./util/logger')
const { jobMaker } = require('./worker/queue')
const schedule = (cronTime, func) => new CronJob({ cronTime, onTick: func, start: true, timeZone: 'Europe/Helsinki' })
@@ -23,37 +27,22 @@ const refreshStudyrightAssociations = async () => {
const refreshFaculties = async () => {
logger.info('Adding jobs to refresh all faculties')
const facultyList = (await faculties()).filter(f => !['Y', 'H99', 'Y01', 'H92', 'H930'].includes(f.code))
for (const faculty of facultyList) {
const faculties = await getFaculties()
for (const faculty of faculties) {
jobMaker.faculty(faculty.code)
}
}
const refreshFaculty = async code => {
logger.info('Started updating faculty')
const start = new Date().getTime()
try {
await updateFacultyOverview(code, 'ALL')
await updateFacultyProgressOverview(code)
const time = new Date().getTime() - start
logger.info(`Updated faculty ${code} (took ${(time / 1000 / 60).toFixed(2)} minutes)`)
} catch (e) {
logger.error({ message: `Failed to update stats for faculty ${code} with type ALL`, meta: `${e}` })
}
await updateFacultyOverview(code, 'ALL')
await updateFacultyProgressOverview(code)
}
const refreshProgrammes = async () => {
logger.info('Refreshing studyprogramme and studytrack overview statistics for all programmes')
// Filters out old programmes and special ones like Fitech studies. Filters also out the programmes starting with
// 2_ or ending with _2. Those programmes are mapped to correct programme (studentProgrammeModuleFixer.js)
const codes = (await getAllProgrammes())
.map(p => p.code)
.filter(
code =>
(code.includes('KH') && !code.startsWith('2_KH') && !code.endsWith('_2')) ||
(code.includes('MH') && !code.startsWith('2_MH') && !code.endsWith('_2')) ||
/^(T)[0-9]{6}$/.test(code)
)
const programmes = await getProgrammesFromStudyRights()
const codes = programmes.map(programme => programme.code).filter(code => isRelevantProgramme(code))
// Ensure that studyright associations are refreshed before launching jobs, otherwise each job will do it
await getAssociations()
@@ -64,13 +53,12 @@ const refreshProgrammes = async () => {
}
const refreshProgramme = async code => {
const associations = await getAssociations()
await updateBasicView(code, '')
await updateStudytrackView(code, '', associations)
await updateStudytrackView(code, '')
let combinedProgramme = combinedStudyprogrammes[code] || ''
const combinedProgramme = combinedStudyprogrammes[code] || ''
await updateBasicView(code, combinedProgramme)
await updateStudytrackView(code, combinedProgramme, associations)
await updateStudytrackView(code, combinedProgramme)
}
const refreshTeacherLeaderboard = async () => {
@@ -95,11 +83,22 @@ const refreshLanguageCenterData = async () => {
logger.info('Language center data refreshed!')
}
const dailyJobs = () => {
refreshFaculties()
refreshProgrammes()
jobMaker.languagecenter()
jobMaker.statistics()
const refreshCloseToGraduating = async () => {
logger.info('Updating students close to graduating...')
const updatedData = await findStudentsCloseToGraduation()
await redisClient.setAsync(CLOSE_TO_GRADUATION_REDIS_KEY, JSON.stringify(updatedData))
logger.info('Students close to graduating updated!')
}
const dailyJobs = async () => {
try {
await refreshProgrammes()
await refreshFaculties()
jobMaker.languagecenter()
jobMaker.statistics()
} catch (error) {
logger.error('Daily jobs failed', error)
}
}
const startCron = () => {
@@ -107,13 +106,22 @@ const startCron = () => {
logger.info('Cronjob for refreshing stats started: runs daily at 23:00.')
schedule('0 23 * * *', async () => {
logger.info('Running daily jobs from cron')
dailyJobs()
await dailyJobs()
})
schedule('0 19 * * 1', async () => {
// This needs to be its own job because refreshing study right associations in `refreshStatistics` causes some study right info to be not available, causing this job to fail
schedule('0 3 * * *', () => {
jobMaker.closeToGraduation()
})
schedule('0 4 * * 3', async () => {
logger.info("Deleting users who haven't logged in for 18 months")
const [, result] = await deleteOutdatedUsers()
logger.info(`Deleted ${result.rowCount} users.`)
})
schedule('0 19 * * 1', () => {
logger.info('Updating students whose studyplans have not been updated recently')
jobMaker.studyplansUpdate(4)
})
schedule('0 10 * * 2', async () => {
schedule('0 10 * * 2', () => {
logger.info('Updating students whose studyplans have not been updated recently')
jobMaker.studyplansUpdate(5)
})
@@ -128,4 +136,5 @@ module.exports = {
refreshProgramme,
refreshProgrammes,
refreshLanguageCenterData,
refreshCloseToGraduating,
}
@@ -1,40 +0,0 @@
const morgan = require('morgan')
const logger = require('../util/logger')
const _ = require('lodash')
// So this appears to be a hack to get neatly formatted stats like response-time etc. from morgan
// without actually using morgan what it's used for (LOGGING REQUESTS!).
// Return undefined from here so that stuff isn't printed to console
// so don't e.g. make it into an async function or it'll print [object Promise] on every request
const accessLogger = morgan((tokens, req, res) => {
const fields = ['method', 'url', 'status', 'response-time', 'remote-addr', 'remote-user', 'user-agent', 'referrer']
const { user } = req
const meta = { ...user }
fields.forEach(field => (meta[field] = tokens[field](req, res)))
meta['time'] = tokens['date'](req, res, 'iso')
if (req.route) {
meta['req-route'] = req.route.path
}
const message = [
`${user.mockedBy ? '(mocking) ' : ''}${user.name}`,
`${(tokens['response-time'](req, res) || '0').split('.')[0]} ms`.padEnd(8, ' '),
tokens['status'](req, res),
tokens['method'](req, res),
tokens['url'](req, res),
].join(' ')
const usingIamRights = user.iamRights.some(programmeCode => tokens['url'](req, res).includes(programmeCode))
const onlyIamRights = !user.isAdmin && user.rights.length === 0
logger.info(message, {
// don't log student list which might be huge
..._.omit(meta, ['studentsUserCanAccess']),
// pass this as a custom field so we can filter by it in graylog
isUsageStats: true,
// needed for Grafana IAM users panel
isIamRights: onlyIamRights || usingIamRights,
})
})
module.exports = accessLogger
@@ -0,0 +1,61 @@
import { Response } from 'express'
import { omit } from 'lodash'
import morgan from 'morgan'
import { FormattedUser, OodikoneRequest } from '../types'
import { getFullStudyProgrammeRights } from '../util'
import logger from '../util/logger'
interface Meta extends FormattedUser {
method?: string
url?: string
status?: string
'response-time'?: string
'remote-addr'?: string
'remote-user'?: string | undefined
'user-agent'?: string
referrer?: string
time?: string
'req-route'?: string
}
// So this appears to be a hack to get neatly formatted stats like response-time etc. from morgan
// without actually using morgan what it's used for (LOGGING REQUESTS!).
// Return undefined from here so that stuff isn't printed to console
// so don't e.g. make it into an async function or it'll print [object Promise] on every request
const accessLogger = morgan((tokens, req: OodikoneRequest, res: Response): undefined => {
const fields = ['method', 'url', 'status', 'response-time', 'remote-addr', 'remote-user', 'user-agent', 'referrer']
const { user } = req
if (!user) {
return
}
const meta: Meta = { ...user }
fields.forEach(field => {
meta[field] = tokens[field](req, res)
})
meta.time = tokens.date(req, res, 'iso')
if (req.route) {
meta['req-route'] = req.route.path
}
const message = [
`${user.mockedBy ? '(mocking) ' : ''}${user.name}`,
`${(tokens['response-time'](req, res) || '0').split('.')[0]} ms`.padEnd(8, ' '),
tokens.status(req, res),
tokens.method(req, res),
decodeURIComponent(tokens.url(req, res) as string),
].join(' ')
const fullStudyProgrammeRights = getFullStudyProgrammeRights(user.programmeRights)
const iamBasedRights = user.programmeRights.filter(right => right.isIamBased)
const usingIamRights = iamBasedRights.some(right => (tokens.url(req, res) as string).includes(right.code))
const onlyIamRights = !user.isAdmin && fullStudyProgrammeRights.length === 0
logger.info(message, {
...omit(meta, ['studentsUserCanAccess']), // Don't log student list which might be huge
isUsageStats: true, // Pass this as a custom field so we can filter by it in Graylog
isIamRights: onlyIamRights || usingIamRights, // Needed for Grafana IAM users panel
})
})
export default accessLogger
-17
View File
@@ -1,17 +0,0 @@
const roles = requiredRoles => async (req, res, next) => {
if (req.user) {
const {
user: { roles },
} = req
if (requiredRoles.some(r => roles.includes(r)) || roles.includes('admin')) {
return next()
}
}
res.status(403).json({ error: 'missing required roles' })
}
module.exports = {
roles,
}
+14
View File
@@ -0,0 +1,14 @@
import { NextFunction, Response } from 'express'
import { OodikoneRequest, Role } from '../types'
export const roles = (requiredRoles: Role[]) => async (req: OodikoneRequest, res: Response, next: NextFunction) => {
if (req.user) {
const { roles } = req.user
if (requiredRoles.some(role => roles.includes(role)) || roles.includes('admin')) {
return next()
}
}
res.status(403).json({ error: 'Missing required roles' })
}
@@ -0,0 +1,144 @@
import * as Sentry from '@sentry/node'
import { NextFunction, Response } from 'express'
import { intersection } from 'lodash'
import { configLogoutUrl, isDev, requiredGroup, serviceProvider } from '../config'
import { getMockedUser, getMockedUserFd, getOrganizationAccess, getUserFd, getUserToska } from '../services/userService'
import { FormattedUser, IamAccess, OodikoneRequest } from '../types'
import { ApplicationError } from '../util/customErrors'
import logger from '../util/logger'
const parseIamGroups = (iamGroups: string) => iamGroups?.split(';') ?? []
const hasRequiredIamGroup = (iamGroups: string[], iamRights: string[]) => {
return intersection(iamGroups, requiredGroup).length > 0 || iamRights.length > 0
}
const getUser = async (
showAsUser: string | undefined,
username: string,
name: string,
email: string,
iamGroups: string[],
specialGroup: Record<string, boolean>,
sisId: string,
iamAccess: IamAccess
) => {
if (showAsUser && specialGroup?.superAdmin) {
return await getMockedUser({ userToMock: showAsUser as string, mockedBy: username as string })
}
return await getUserToska({
username: username as string,
name: name as string,
email: email as string,
iamGroups,
specialGroup,
sisId: sisId as string,
iamAccess,
})
}
type Headers = {
host?: string
'user-agent'?: string
accept?: string
'accept-language'?: string
'accept-encoding'?: string
referer?: string
displayname?: string
hygroupcn?: string
hypersonsisuid?: string
mail?: string
remote_user?: string
'shib-session-id'?: string
shib_logout_url?: string
uid?: string
'x-show-as-user'?: string
connection?: string
cookie?: string
'sec-fetch-dest'?: string
'sec-fetch-mode'?: string
'sec-fetch-site'?: string
'if-none-match'?: string
priority?: string
}
const toskaUserMiddleware = async (req: OodikoneRequest, _res: Response, next: NextFunction) => {
const {
'shib-session-id': sessionId,
'x-show-as-user': showAsUser,
displayname: name,
hygroupcn,
hypersonsisuid: sisId,
mail: email,
shib_logout_url: logoutUrl,
uid: username,
} = req.headers as Headers
const missingHeaders: string[] = []
if (!sessionId) missingHeaders.push('shib-session-id')
if (!username) missingHeaders.push('uid')
if (missingHeaders.length > 0) {
throw new ApplicationError(
`Not enough data in request headers, the following headers were missing: ${missingHeaders.join(', ')}`,
403,
{ logoutUrl }
)
}
const iamGroups = parseIamGroups(hygroupcn as string)
const { iamAccess = {}, specialGroup = {} } = await getOrganizationAccess(sisId as string, iamGroups)
const iamRights = Object.keys(iamAccess)
if (!hasRequiredIamGroup(iamGroups, iamRights)) {
logger.error({
message: 'User does not have required iam group',
meta: { username, name, email, iamGroups, iamRights },
})
throw new ApplicationError(`User '${username}' does not have required iam group`, 403, { logoutUrl })
}
const user = await getUser(showAsUser, username!, name!, email!, iamGroups, specialGroup, sisId!, iamAccess)
if (!user) {
throw new ApplicationError(`Username ${username} not found.`, 403, { logoutUrl })
}
Sentry.setUser({ username: user.mockedBy ?? username! })
req.user = user
req.logoutUrl = logoutUrl as string
next()
}
const fdUserMiddleware = async (req: OodikoneRequest, _res: Response, next: NextFunction) => {
const { remote_user: remoteUser, 'x-show-as-user': showAsUser } = req.headers
if (!remoteUser) {
throw new ApplicationError('Not enough data in request headers, remote_user was missing', 403, { configLogoutUrl })
}
let user: FormattedUser | null
// getMockedUser in production requires the superAdmin role, which is only available
// via iamGroups, so it's now only implemented for the dev environment
if (showAsUser && isDev) {
user = await getMockedUserFd({ userToMock: showAsUser as string, mockedBy: remoteUser as string })
} else {
user = await getUserFd({ username: remoteUser as string })
}
if (!user) {
throw new ApplicationError(`Could not grant access with the eppn ${remoteUser}.`, 403, { configLogoutUrl })
}
req.user = user
req.logoutUrl = configLogoutUrl
next()
}
const currentUserMiddleware = serviceProvider === 'Toska' ? toskaUserMiddleware : fdUserMiddleware
export default currentUserMiddleware
@@ -1,69 +0,0 @@
const Sentry = require('@sentry/node')
const { ApplicationError } = require('../util/customErrors')
const { getUser, getMockedUser, getOrganizationAccess } = require('../services/userService')
const { requiredGroup } = require('../conf-backend')
const _ = require('lodash')
const logger = require('../util/logger')
const parseIamGroups = iamGroups => iamGroups?.split(';').filter(Boolean) ?? []
const hasRequiredIamGroup = (iamGroups, iamRights) =>
_.intersection(iamGroups, requiredGroup).length > 0 || iamRights.length > 0
const currentUserMiddleware = async (req, _res, next) => {
const {
'shib-session-id': sessionId,
'x-show-as-user': showAsUser,
displayname: name,
hygroupcn,
hypersonsisuid: sisId,
mail: email,
shib_logout_url: logoutUrl,
uid: username,
} = req.headers
const missingHeaders = []
if (!sessionId) missingHeaders.push('shib-session-id')
if (!username) missingHeaders.push('uid')
if (missingHeaders.length > 0) {
throw new ApplicationError(
`Not enough data in request headers, the following headers were missing: ${missingHeaders.join(', ')}`,
403,
{ logoutUrl }
)
}
const iamGroups = parseIamGroups(hygroupcn)
const { access = {}, specialGroup = {} } = await getOrganizationAccess({ id: sisId, iamGroups })
const iamRights = Object.keys(access)
if (!hasRequiredIamGroup(iamGroups, iamRights)) {
logger.error({ message: 'User does not have required iam group', meta: { iamGroups, iamRights } })
throw new ApplicationError('User does not have required iam group', 403, { logoutUrl })
}
let user = await getUser({
username,
name,
email,
iamGroups,
iamRights,
specialGroup,
sisId,
})
if (showAsUser && user.isAdmin) {
user = await getMockedUser({ userToMock: showAsUser, mockedBy: username })
}
Sentry.setUser({ username: user.mockedBy ?? username })
req.user = user
req.logoutUrl = logoutUrl
next()
}
module.exports = currentUserMiddleware
@@ -0,0 +1,21 @@
import * as Sentry from '@sentry/node'
import { NextFunction, Response } from 'express'
import { OodikoneRequest } from '../types'
import { ApplicationError } from '../util/customErrors'
import logger from '../util/logger'
const errorHandler = (error: any, _req: OodikoneRequest, res: Response, next: NextFunction) => {
logger.error(error.message, { error })
Sentry.captureException(error)
if (res.headersSent) {
return next(error)
}
const normalizedError = error instanceof ApplicationError ? error : new ApplicationError(error.message)
return res.status(normalizedError.status).json(normalizedError)
}
export default errorHandler
@@ -1,19 +0,0 @@
const Sentry = require('@sentry/node')
const { ApplicationError } = require('../util/customErrors')
const logger = require('../util/logger')
const errorHandler = (error, req, res, next) => {
logger.error(`${error.message} ${error.name} ${error.stack}`)
Sentry.captureException(error)
if (res.headersSent) {
return next(error)
}
const normalizedError = error instanceof ApplicationError ? error : new ApplicationError(error.message)
return res.status(normalizedError.status).json(normalizedError)
}
module.exports = errorHandler
@@ -0,0 +1,10 @@
import headersMiddleware from 'unfuck-utf8-headers-middleware'
import { serviceProvider } from '../config'
const headersToska = ['uid', 'displayName', 'shib-session-id', 'hyGroupCn', 'mail', 'hyPersonSisuId']
const headersOther = ['remote_user']
const headers = serviceProvider === 'Toska' ? headersToska : headersOther
export default headersMiddleware(headers)
@@ -1,5 +0,0 @@
const headersMiddleware = require('unfuck-utf8-headers-middleware')
const headers = ['uid', 'displayName', 'shib-session-id', 'hyGroupCn', 'mail', 'hyPersonSisuId']
module.exports = headersMiddleware(headers)
@@ -0,0 +1,87 @@
/* eslint-disable import/no-cycle */
import { InferAttributes } from 'sequelize'
import {
BelongsTo,
Column,
CreatedAt,
DataType,
ForeignKey,
HasMany,
Model,
PrimaryKey,
Table,
UpdatedAt,
} from 'sequelize-typescript'
import { EnrollmentType, ExtentCode } from '../types'
import { Organization } from './organization'
import { SISStudyRightElement } from './SISStudyRightElement'
import { Student } from './student'
import { Studyplan } from './studyplan'
import { StudyrightExtent } from './studyrightExtent'
export type SemesterEnrollment = {
type: EnrollmentType
semester: number
statutoryAbsence?: boolean
}
@Table({
underscored: true,
tableName: 'sis_study_rights',
})
export class SISStudyRight extends Model<InferAttributes<SISStudyRight>> {
@PrimaryKey
@Column(DataType.STRING)
id!: string
@ForeignKey(() => Organization)
@Column(DataType.STRING)
facultyCode!: string
@BelongsTo(() => Organization, { foreignKey: 'facultyCode', targetKey: 'code' })
organization!: Organization
@HasMany(() => Studyplan)
studyPlans!: Studyplan[]
@HasMany(() => SISStudyRightElement, { foreignKey: 'studyRightId' })
studyRightElements!: SISStudyRightElement[]
@Column(DataType.DATE)
startDate!: Date
@Column(DataType.DATE)
endDate!: Date
@Column(DataType.DATE)
studyStartDate!: Date
@Column(DataType.BOOLEAN)
cancelled!: boolean
@ForeignKey(() => Student)
@Column(DataType.STRING)
studentNumber!: string
@BelongsTo(() => Student)
student!: Student
@ForeignKey(() => StudyrightExtent)
@Column(DataType.INTEGER)
extentCode!: ExtentCode
@Column(DataType.STRING)
admissionType!: string
@Column(DataType.JSONB)
semesterEnrollments!: SemesterEnrollment[] | null
@CreatedAt
@Column(DataType.DATE)
createdAt!: Date
@UpdatedAt
@Column(DataType.DATE)
updatedAt!: Date
}
@@ -0,0 +1,65 @@
/* eslint-disable import/no-cycle */
import { InferAttributes } from 'sequelize'
import {
BelongsTo,
Column,
CreatedAt,
DataType,
ForeignKey,
Model,
PrimaryKey,
Table,
UpdatedAt,
} from 'sequelize-typescript'
import { Name, Phase, StudyTrack } from '../types'
import { SISStudyRight } from './SISStudyRight'
@Table({
underscored: true,
tableName: 'sis_study_right_elements',
})
export class SISStudyRightElement extends Model<InferAttributes<SISStudyRightElement>> {
@PrimaryKey
@Column(DataType.STRING)
id!: string
@Column(DataType.DATE)
startDate!: Date
@Column(DataType.DATE)
endDate!: Date
@Column(DataType.BOOLEAN)
graduated!: boolean
@Column(DataType.INTEGER)
phase!: Phase
@ForeignKey(() => SISStudyRight)
@Column(DataType.STRING)
studyRightId!: string
@BelongsTo(() => SISStudyRight, { foreignKey: 'studyRightId' })
studyRight!: SISStudyRight
@Column(DataType.STRING)
code!: string
@Column(DataType.JSONB)
name!: Name
@Column(DataType.JSONB)
studyTrack!: StudyTrack | null
@Column(DataType.STRING)
degreeProgrammeType!: string
@CreatedAt
@Column(DataType.DATE)
createdAt!: Date
@UpdatedAt
@Column(DataType.DATE)
updatedAt!: Date
}
-66
View File
@@ -1,66 +0,0 @@
const { Model, STRING, DATE, JSONB, BOOLEAN } = require('sequelize')
const { dbConnections } = require('../database/connection')
class Course extends Model {}
Course.init(
{
id: {
type: STRING,
primaryKey: true,
},
code: {
type: STRING,
},
name: {
type: JSONB,
},
latest_instance_date: {
type: DATE,
},
is_study_module: {
type: BOOLEAN,
},
coursetypecode: {
type: STRING,
},
startdate: {
type: DATE,
},
enddate: {
type: DATE,
},
max_attainment_date: {
type: DATE,
},
min_attainment_date: {
type: DATE,
},
createdAt: {
field: 'created_at',
type: DATE,
},
updatedAt: {
field: 'updated_at',
type: DATE,
},
substitutions: {
type: JSONB,
},
course_unit_type: {
type: STRING,
},
mainCourseCode: {
field: 'main_course_code',
type: STRING,
},
},
{
underscored: false,
sequelize: dbConnections.sequelize,
modelName: 'course',
tableName: 'course',
}
)
module.exports = Course
+100
View File
@@ -0,0 +1,100 @@
/* eslint-disable import/no-cycle */
import { InferAttributes } from 'sequelize'
import {
BelongsTo,
BelongsToMany,
Column,
CreatedAt,
DataType,
ForeignKey,
HasMany,
Model,
PrimaryKey,
Table,
UpdatedAt,
} from 'sequelize-typescript'
import { Name } from '../types'
import { CourseProvider } from './courseProvider'
import { CourseType } from './courseType'
import { Credit } from './credit'
import { Enrollment } from './enrollment'
import { Organization } from './organization'
@Table({
underscored: false,
modelName: 'course',
tableName: 'course',
})
export class Course extends Model<InferAttributes<Course>> {
@PrimaryKey
@Column(DataType.STRING)
id!: string
@ForeignKey(() => Course)
@Column(DataType.STRING)
code!: string
@ForeignKey(() => CourseType)
@Column(DataType.STRING)
coursetypecode!: string
@BelongsTo(() => CourseType, { foreignKey: 'coursetypecode', targetKey: 'coursetypecode' })
courseType!: CourseType
@HasMany(() => Credit, { foreignKey: 'course_id', sourceKey: 'id' })
credits!: Credit[]
@HasMany(() => Enrollment, { foreignKey: 'course_id' })
enrollments!: Enrollment[]
@BelongsToMany(() => Organization, () => CourseProvider, 'coursecode')
organizations!: Organization[]
@Column(DataType.BOOLEAN)
is_study_module!: boolean
@Column(DataType.JSONB)
name!: Name
@Column(DataType.DATE)
latest_instance_date!: Date
@Column(DataType.DATE)
startdate!: Date
@Column(DataType.DATE)
enddate!: Date
@Column(DataType.DATE)
max_attainment_date!: Date
@Column(DataType.DATE)
min_attainment_date!: Date
@CreatedAt
@Column({
field: 'created_at',
type: DataType.DATE,
})
createdAt!: Date
@UpdatedAt
@Column({
field: 'updated_at',
type: DataType.DATE,
})
updatedAt!: Date
@Column(DataType.JSONB)
substitutions!: string[]
@Column(DataType.STRING)
course_unit_type!: string
@Column({
field: 'main_course_code',
type: DataType.STRING,
})
mainCourseCode!: string
}
@@ -1,54 +0,0 @@
const { Model, STRING, DATE, JSONB } = require('sequelize')
const { dbConnections } = require('../database/connection')
class CourseProvider extends Model {}
CourseProvider.init(
{
composite: {
type: STRING,
unique: true,
},
coursecode: {
type: STRING,
references: {
model: 'course',
key: 'id',
},
onUpdate: 'cascade',
onDelete: 'cascade',
},
shares: {
type: JSONB,
},
organizationcode: {
type: STRING,
references: {
model: 'organization',
key: 'id',
},
onUpdate: 'cascade',
onDelete: 'cascade',
},
createdAt: {
type: DATE,
},
updatedAt: {
type: DATE,
},
},
{
underscored: true,
sequelize: dbConnections.sequelize,
modelName: 'course_provider',
tableName: 'course_providers',
indexes: [
{
unique: true,
fields: ['coursecode', 'organizationcode'],
},
],
}
)
module.exports = CourseProvider
@@ -0,0 +1,42 @@
/* eslint-disable import/no-cycle */
import { InferAttributes } from 'sequelize'
import { Column, CreatedAt, DataType, ForeignKey, Model, PrimaryKey, Table, UpdatedAt } from 'sequelize-typescript'
import { Course } from './course'
import { Organization } from './organization'
@Table({
underscored: true,
modelName: 'course_provider',
tableName: 'course_providers',
indexes: [
{
unique: true,
fields: ['coursecode', 'organizationcode'],
},
],
})
export class CourseProvider extends Model<InferAttributes<CourseProvider>> {
@PrimaryKey
@Column(DataType.STRING)
composite!: string
@ForeignKey(() => Course)
@Column(DataType.STRING)
coursecode!: string
@Column(DataType.JSONB)
shares!: Array<{ share: number; startDate?: string; endDate?: string }> | null
@ForeignKey(() => Organization)
@Column(DataType.STRING)
organizationcode!: string
@CreatedAt
@Column(DataType.DATE)
createdAt!: Date
@UpdatedAt
@Column(DataType.DATE)
updatedAt!: Date
}
-30
View File
@@ -1,30 +0,0 @@
const { Model, STRING, DATE, JSONB } = require('sequelize')
const { dbConnections } = require('../database/connection')
class CourseType extends Model {}
CourseType.init(
{
coursetypecode: {
type: STRING,
primaryKey: true,
},
name: {
type: JSONB,
},
createdAt: {
type: DATE,
},
updatedAt: {
type: DATE,
},
},
{
underscored: true,
sequelize: dbConnections.sequelize,
modelName: 'course_type',
tableName: 'course_types',
}
)
module.exports = CourseType
+31
View File
@@ -0,0 +1,31 @@
/* eslint-disable import/no-cycle */
import { InferAttributes } from 'sequelize'
import { Column, CreatedAt, DataType, HasMany, Model, PrimaryKey, Table, UpdatedAt } from 'sequelize-typescript'
import { Name } from '../types'
import { Course } from './course'
@Table({
underscored: true,
modelName: 'course_type',
tableName: 'course_types',
})
export class CourseType extends Model<InferAttributes<CourseType>> {
@PrimaryKey
@Column(DataType.STRING)
coursetypecode!: string
@HasMany(() => Course)
courses!: Course[]
@Column(DataType.JSONB)
name!: Required<Name>
@CreatedAt
@Column(DataType.DATE)
createdAt!: Date
@UpdatedAt
@Column(DataType.DATE)
updatedAt!: Date
}
-101
View File
@@ -1,101 +0,0 @@
const { Model, DATE, INTEGER, STRING, DOUBLE, BOOLEAN } = require('sequelize')
const { dbConnections } = require('../database/connection')
class Credit extends Model {}
Credit.init(
{
id: {
primaryKey: true,
type: STRING,
},
grade: {
type: STRING,
},
student_studentnumber: {
type: STRING,
references: {
model: 'student',
key: 'studentnumber',
},
onUpdate: 'cascade',
onDelete: 'cascade',
},
credits: {
type: DOUBLE,
},
createdate: {
type: DATE,
},
credittypecode: {
type: INTEGER,
references: {
model: 'credit_types',
key: 'credittypecode',
},
onUpdate: 'cascade',
onDelete: 'cascade',
},
attainment_date: {
type: DATE,
},
course_code: {
type: STRING,
},
course_id: {
type: STRING,
references: {
model: 'course',
key: 'id',
},
onUpdate: 'cascade',
onDelete: 'cascade',
},
semester_composite: {
type: STRING,
references: {
model: 'semesters',
key: 'composite',
},
onUpdate: 'cascade',
onDelete: 'cascade',
},
semestercode: {
type: INTEGER,
},
isStudyModule: {
type: BOOLEAN,
},
org: {
type: STRING,
},
createdAt: {
type: DATE,
},
updatedAt: {
type: DATE,
},
language: {
type: STRING,
},
is_open: {
type: BOOLEAN,
},
studyright_id: {
type: STRING,
allowNull: true,
references: {
model: 'studyright',
key: 'studyrightid',
},
},
},
{
underscored: false,
sequelize: dbConnections.sequelize,
modelName: 'credit',
tableName: 'credit',
}
)
module.exports = Credit
+117
View File
@@ -0,0 +1,117 @@
/* eslint-disable import/no-cycle */
import { InferAttributes } from 'sequelize'
import {
BelongsTo,
BelongsToMany,
Column,
CreatedAt,
DataType,
ForeignKey,
Model,
PrimaryKey,
Table,
UpdatedAt,
} from 'sequelize-typescript'
import { CreditTypeCode } from '../types'
import { Course } from './course'
import { CreditTeacher } from './creditTeacher'
import { CreditType } from './creditType'
import { Semester } from './semester'
import { Student } from './student'
import { Studyright } from './studyright'
import { Teacher } from './teacher'
@Table({
underscored: false,
modelName: 'credit',
tableName: 'credit',
})
export class Credit extends Model<InferAttributes<Credit>> {
@PrimaryKey
@Column(DataType.STRING)
id!: string
@Column(DataType.STRING)
grade!: string
@ForeignKey(() => Student)
@Column(DataType.STRING)
student_studentnumber!: string
@BelongsTo(() => Student, { foreignKey: 'student_studentnumber', targetKey: 'studentnumber' })
student!: Student
@BelongsTo(() => Semester, { foreignKey: 'semester_composite' })
semester!: Semester
@Column(DataType.DOUBLE)
credits!: number
@ForeignKey(() => CreditType)
@Column(DataType.INTEGER)
credittypecode!: CreditTypeCode
@BelongsTo(() => CreditType, { foreignKey: 'credittypecode', targetKey: 'credittypecode' })
creditType!: CreditType
@Column(DataType.DATE)
createdate!: Date
@Column(DataType.DATE)
attainment_date!: Date
@BelongsToMany(() => Teacher, () => CreditTeacher, 'credit_id')
teachers!: Teacher[]
@Column(DataType.STRING)
course_code!: string
@BelongsTo(() => Course, { foreignKey: 'course_id' })
course!: Course
@ForeignKey(() => Course)
@Column(DataType.STRING)
course_id!: string
@Column(DataType.STRING)
semester_composite!: string
@Column(DataType.INTEGER)
semestercode!: number
@Column(DataType.BOOLEAN)
isStudyModule!: boolean
@Column(DataType.STRING)
org!: string
@Column(DataType.STRING)
language!: string
@Column(DataType.BOOLEAN)
is_open!: boolean
@ForeignKey(() => Studyright)
@Column(DataType.STRING)
studyright_id!: string
@BelongsTo(() => Studyright)
studyright!: Studyright
@CreatedAt
@Column(DataType.DATE)
createdAt!: Date
@UpdatedAt
@Column(DataType.DATE)
updatedAt!: Date
static passed: ({ credittypecode }: { credittypecode: CreditTypeCode }) => boolean
static failed: ({ credittypecode }: { credittypecode: CreditTypeCode }) => boolean
static improved: ({ credittypecode }: { credittypecode: CreditTypeCode }) => boolean
static notUnnecessary: ({ credits }: { credits: number }) => boolean
}
@@ -1,45 +0,0 @@
const { Model, STRING, DATE } = require('sequelize')
const { dbConnections } = require('../database/connection')
class CreditTeacher extends Model {}
CreditTeacher.init(
{
composite: {
type: STRING,
unique: true,
},
credit_id: {
type: STRING,
references: {
model: 'credit',
key: 'id',
},
onUpdate: 'cascade',
onDelete: 'cascade',
},
teacher_id: {
type: STRING,
references: {
model: 'teacher',
key: 'id',
},
onUpdate: 'cascade',
onDelete: 'cascade',
},
createdAt: {
type: DATE,
},
updatedAt: {
type: DATE,
},
},
{
underscored: false,
sequelize: dbConnections.sequelize,
modelName: 'credit_teacher',
tableName: 'credit_teachers',
}
)
module.exports = CreditTeacher
@@ -0,0 +1,44 @@
/* eslint-disable import/no-cycle */
import { InferAttributes } from 'sequelize'
import {
Column,
CreatedAt,
DataType,
ForeignKey,
Model,
PrimaryKey,
Table,
Unique,
UpdatedAt,
} from 'sequelize-typescript'
import { Credit } from './credit'
import { Teacher } from './teacher'
@Table({
underscored: false,
modelName: 'credit_teacher',
tableName: 'credit_teachers',
})
export class CreditTeacher extends Model<InferAttributes<CreditTeacher>> {
@PrimaryKey
@Unique
@Column(DataType.STRING)
composite!: string
@ForeignKey(() => Credit)
@Column(DataType.STRING)
credit_id!: string
@ForeignKey(() => Teacher)
@Column(DataType.STRING)
teacher_id!: string
@CreatedAt
@Column(DataType.DATE)
createdAt!: Date
@UpdatedAt
@Column(DataType.DATE)
updatedAt!: Date
}
-30
View File
@@ -1,30 +0,0 @@
const { Model, INTEGER, DATE, JSONB } = require('sequelize')
const { dbConnections } = require('../database/connection')
class CreditType extends Model {}
CreditType.init(
{
credittypecode: {
primaryKey: true,
type: INTEGER,
},
name: {
type: JSONB,
},
createdAt: {
type: DATE,
},
updatedAt: {
type: DATE,
},
},
{
underscored: true,
sequelize: dbConnections.sequelize,
modelName: 'credit_type',
tableName: 'credit_types',
}
)
module.exports = CreditType
+26
View File
@@ -0,0 +1,26 @@
import { InferAttributes } from 'sequelize'
import { Column, CreatedAt, DataType, Model, PrimaryKey, Table, UpdatedAt } from 'sequelize-typescript'
import { CreditTypeCode, Name } from '../types'
@Table({
underscored: true,
modelName: 'credit_type',
tableName: 'credit_types',
})
export class CreditType extends Model<InferAttributes<CreditType>> {
@PrimaryKey
@Column(DataType.INTEGER)
credittypecode!: CreditTypeCode
@Column(DataType.JSONB)
name!: Required<Name>
@CreatedAt
@Column(DataType.DATE)
createdAt!: Date
@UpdatedAt
@Column(DataType.DATE)
updatedAt!: Date
}

Some files were not shown because too many files have changed in this diff Show More