Compare commits

...
792 Commits
Author SHA1 Message Date
Rochet2andGitHub 7b7a7e0e66 Merge pull request #1317 from UniversityOfHelsinkiCS/trunk
fix studyprogramme column 820ab42
2019-08-23 11:44:12 +03:00
esakemp f7d89abd87 Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-08-23 08:43:11 +03:00
esakemp 820ab42363 fix studyprogramme column 2019-08-23 08:34:21 +03:00
Rochet2andGitHub 4d037effab Merge pull request #1313 from UniversityOfHelsinkiCS/trunk
refactor, fix bugs, add error messages to tags
2019-08-22 17:11:27 +03:00
Rochet2 a83cf3f736 refactor, fix bugs, add error messages to tags 2019-08-22 16:53:19 +03:00
Rochet2andGitHub 67591f4d58 Merge pull request #1311 from UniversityOfHelsinkiCS/trunk
columns and fixeszzz
2019-08-22 14:56:24 +03:00
Rochet2 8835540921 Merge branch 'trunk' of github.com:UniversityOfHelsinkiCS/oodikone into trunk 2019-08-22 14:35:46 +03:00
Rochet2 c081bf5c7a Make sentry catch all errors, we can filter them out if we need to 2019-08-22 14:33:51 +03:00
esakempandGitHub 2da21bd823 Merge pull request #1311 from UniversityOfHelsinkiCS/trunk
columns and fixeszzz
2019-08-22 14:02:53 +03:00
esakempandGitHub 2442a09561 lol git 2019-08-22 12:38:02 +03:00
esakempandGitHub 35a7437bce Merge branch 'master' into trunk 2019-08-22 12:34:41 +03:00
esakemp 555100a195 new columns for custom/course populations 2019-08-22 12:08:07 +03:00
esakemp e241887ba6 small fix 2019-08-22 10:53:36 +03:00
esakemp 9860713af6 add tag column 2019-08-22 10:18:56 +03:00
esakempandGitHub ac647d3639 Merge pull request #1308 from UniversityOfHelsinkiCS/trunk
custom population minthhhhhh
2019-08-22 09:33:32 +03:00
esakemp c9ea8d9441 remove useless redux files 2019-08-22 09:16:45 +03:00
esakemp 18df5ddd51 refactoring, fixing and some other garbage 2019-08-22 09:03:56 +03:00
esakempandGitHub 5b88352264 Merge pull request #1304 from UniversityOfHelsinkiCS/trunk
portsari vs pesimis
2019-08-21 12:34:03 +03:00
esakemp 73bd2a8f2e some fixes and psychosis 2019-08-21 12:13:44 +03:00
Rochet2andGitHub af93d66fc5 Merge pull request #1298 from UniversityOfHelsinkiCS/trunk
Course statistics improvements
2019-08-21 10:53:33 +03:00
Rochet2 2253bd2c17 Fix tests 2019-08-21 00:20:58 +03:00
Rochet2 8606139fe8 Merge branch 'trunk' of github.com:UniversityOfHelsinkiCS/oodikone into trunk 2019-08-20 23:40:42 +03:00
Rochet2 8d363d2eae Make duplicate code search symmetric 2019-08-20 23:40:33 +03:00
Rochet2 e600dc081b Remove duplicate code 2019-08-20 23:39:58 +03:00
Rochet2 99549ea564 Apparently separate is a thing. Why is it in yearFilter? Lets move it and fix it. 2019-08-20 23:17:11 +03:00
Rochet2 986984b0d8 Fix course statistics from and to years properly this time (why redux, olli?) 2019-08-20 22:40:52 +03:00
Rochet2 d8c4af1b22 Fix hacks by olli and esa 2019-08-20 22:35:59 +03:00
Rochet2 ee8609418a Students is no longer a set 2019-08-20 22:30:12 +03:00
Rochet2 b13ff903e6 Sort course stat tables in descending order 2019-08-20 22:21:58 +03:00
Rochet2 a7640c44be Match any course code containing given string 2019-08-20 18:29:37 +03:00
Rochet2 f2592d02a8 Unify en,sv,fi in open uni courses 2019-08-20 18:19:45 +03:00
Rochet2andGitHub 4aa5e948e1 Merge pull request #1297 from UniversityOfHelsinkiCS/trunk
Remove course statistics years from form, improvements to custom population
2019-08-20 17:30:16 +03:00
Rochet2andGitHub 7e178754f5 Merge branch 'master' into trunk 2019-08-20 17:09:23 +03:00
Rochet2 e2422b0015 Merge branch 'trunk' of github.com:UniversityOfHelsinkiCS/oodikone into trunk 2019-08-20 16:17:59 +03:00
Rochet2 74fe43adb6 Remove from and to years from course statistics, closes https://github.com/UniversityOfHelsinkiCS/oodikone/issues/1273 2019-08-20 16:17:43 +03:00
esakemp 7a60d470b1 small bug fixes 2019-08-20 15:38:15 +03:00
esakemp d070db30f5 Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-08-20 15:15:50 +03:00
esakemp 49ff792a4b add stuff to custompop 2019-08-20 15:14:17 +03:00
Rochet2andGitHub 383beb77b4 Merge pull request #1295 from UniversityOfHelsinkiCS/trunk
Quick fixes
2019-08-20 14:51:31 +03:00
esakemp 3b8a8ec9ec add student table to custompop 2019-08-20 14:43:23 +03:00
Rochet2 04943c04e8 Merge branch 'trunk' of github.com:UniversityOfHelsinkiCS/oodikone into trunk 2019-08-20 14:42:00 +03:00
Rochet2 9438696dcb Update studentnumber list 2019-08-20 14:41:32 +03:00
esakemp 0f868f32ba tag fixors 2019-08-20 14:18:47 +03:00
esakempandGitHub a177f1daab Merge pull request #1285 from UniversityOfHelsinkiCS/trunk
enormous bug fix
2019-08-20 09:45:42 +03:00
esakemp 815eb09a9e bug fix 2019-08-20 09:25:47 +03:00
Rochet2andGitHub 608a11625e Merge pull request #1283 from UniversityOfHelsinkiCS/trunk
Merge and run
2019-08-19 17:17:19 +03:00
Rochet2 1c40f9b118 Fix tests 2019-08-19 16:50:34 +03:00
Rochet2 4408ee04e9 Add last update timestamp to main page 2019-08-19 16:47:59 +03:00
Rochet2 c838513347 Optimize going from users list to a single user and back 2019-08-19 16:31:20 +03:00
Rochet2 125cb6fc09 Fix unclear switch 2019-08-19 15:53:05 +03:00
Rochet2 7d9202e689 Disable cronjobs when not in production 2019-08-19 15:44:28 +03:00
Rochet2 a59a7a7536 Fine tune updater schedules 2019-08-19 15:27:47 +03:00
Rochet2 4cffd7b601 Fix active students not recognised 2019-08-19 15:15:47 +03:00
Rochet2andGitHub 755d765593 Merge pull request #1282 from UniversityOfHelsinkiCS/trunk
UI, course statistics and general improvements
2019-08-19 14:54:09 +03:00
Rochet2 3ee69da8c9 Try fix F5 changing statistics 2019-08-19 14:37:21 +03:00
Rochet2 e021ea1f93 Fix missing nondegreeStudents, try optimize course statistics query 2019-08-18 00:55:46 +03:00
Rochet2 be9d1ddcb3 Fix CI build output (circleci doesnt seem to like --progress) 2019-08-17 18:40:27 +03:00
Rochet2 e7214e071d Optimization 2019-08-16 22:32:21 +03:00
Rochet2 463488c220 Fix https://github.com/UniversityOfHelsinkiCS/oodikone/issues/1243 2019-08-16 19:27:18 +03:00
Rochet2 c980b2089b Merge branch 'trunk' of github.com:UniversityOfHelsinkiCS/oodikone into trunk 2019-08-16 17:16:15 +03:00
Rochet2 dd6573ae54 Fix https://github.com/UniversityOfHelsinkiCS/oodikone/issues/1229 2019-08-16 17:16:07 +03:00
OlliandGitHub 8e10838d13 Merge pull request #1281 from UniversityOfHelsinkiCS/trunk
Added graph to faculty stats
2019-08-16 13:44:46 +03:00
OlliandGitHub 061bedc65a Merge branch 'master' into trunk 2019-08-16 13:34:18 +03:00
Warro 5dd94ac312 Added graph to faculty stats 2019-08-16 13:20:37 +03:00
Rochet2 df5bb910b9 Log some server errors 2019-08-15 21:41:19 +03:00
Rochet2 6951d4f361 Remove unused code 2019-08-15 18:22:38 +03:00
Rochet2 1a7ecce8ba Add everyone to error page, generate random data 2019-08-15 15:35:11 +03:00
Rochet2 478ff07a11 Fix faculty dropdown 2019-08-15 15:33:41 +03:00
esakempandGitHub 6607f8158b Merge pull request #1279 from UniversityOfHelsinkiCS/trunk
Faculty programmes' stats
2019-08-15 15:26:15 +03:00
Warro 35f46c36d6 Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-08-15 15:06:28 +03:00
Warro bbd88e882d Refactored faculty stats and added programme stats 2019-08-15 15:06:25 +03:00
esakemp 1a6ceadc43 some garbage 2019-08-15 14:45:48 +03:00
esakempandGitHub ecad10612f Merge pull request #1278 from UniversityOfHelsinkiCS/trunk
fix warning that slipped to staging
2019-08-15 14:03:21 +03:00
esakemp c2af8ac216 fix warning 2019-08-15 13:46:20 +03:00
esakempandGitHub e8a1e46fbd Merge pull request #1276 from UniversityOfHelsinkiCS/trunk
bug fix and proof of concept
2019-08-15 13:10:15 +03:00
esakemp e817a2a39d trash implementation of custom pop for proof of concept 2019-08-15 12:49:03 +03:00
esakemp 79a5bbdc37 coursepopulation bug fix 2019-08-15 09:10:19 +03:00
OlliandGitHub 9c8e852c89 Merge pull request #1275 from UniversityOfHelsinkiCS/trunk
Bug fixes and amount of finns to overview and made links more linkier
2019-08-14 17:13:08 +03:00
Warro 137a9438a8 Fixed bug where clicking 'New query' made it seem like the following course search failed 2019-08-14 16:44:53 +03:00
Warro 6bc0b595bd Added cursor pointer to all link icons 2019-08-14 15:55:58 +03:00
Warro a8865e8419 Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-08-14 15:35:18 +03:00
Warro de4bcf1bf1 Added nationalities to throughput data and amount of finns to study programme overview 2019-08-14 15:35:13 +03:00
esakemp ce0a416cc8 amazing bug free code 2019-08-14 15:04:14 +03:00
esakemp bac31d826b finally fixed 2019-08-14 14:37:46 +03:00
esakemp 41fd6d98ca small bug fix 2019-08-14 09:15:04 +03:00
esakemp 279cbf0e2a Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-08-13 15:36:36 +03:00
esakemp 6e13d61057 lint 2019-08-13 15:36:24 +03:00
esakemp 7977ec8e1f bug hunting 2019-08-13 15:30:48 +03:00
esakempandGitHub 3d56421c50 Merge pull request #1264 from UniversityOfHelsinkiCS/trunk
Fix release (really now) and course statistics programme multi selection
2019-08-13 14:53:34 +03:00
Warro e5a78cfda7 Fixed warning in course stats 2019-08-13 14:53:14 +03:00
Warro 634156bf36 Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-08-13 14:36:56 +03:00
Rochet2andGitHub 660e26751e Merge branch 'master' into trunk 2019-08-13 14:28:02 +03:00
Rochet2andGitHub 5568613874 Merge pull request #1263 from Rochet2/circleci
Circleci
2019-08-13 14:27:31 +03:00
Rochet2andGitHub 0674116369 Update config.yml 2019-08-13 14:25:20 +03:00
Rochet2andGitHub 37d4f19b65 Update config.yml 2019-08-13 14:22:06 +03:00
esakempandGitHub ec01b859ca Merge pull request #1260 from UniversityOfHelsinkiCS/trunk
Add tag build (for releases)
2019-08-13 14:14:50 +03:00
Warro d812df5826 Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-08-13 14:09:01 +03:00
Warro 62ef257c34 Made programmes responsive towards the time filter and added possibility to select excluded programmes in course statistics 2019-08-13 14:08:55 +03:00
Rochet2andGitHub 0511b6a774 Merge pull request #1259 from Rochet2/circleci
Circleci
2019-08-13 13:57:02 +03:00
Rochet2 5030f26b87 added tag build 2019-08-13 13:51:04 +03:00
esakempandGitHub 91bc8e8854 Merge pull request #1256 from UniversityOfHelsinkiCS/trunk
jami and fix
2019-08-13 12:57:37 +03:00
esakemp 92c5f577fd fix bug with refresh in course population 2019-08-13 12:39:49 +03:00
esakemp 3cdd03643a jami filter 2019-08-13 12:15:24 +03:00
esakempandGitHub b974d08ac1 Merge pull request #1253 from UniversityOfHelsinkiCS/trunk
tag stuff
2019-08-13 11:51:07 +03:00
esakemp 78f80bf8ab tag fixordrs 2019-08-13 11:31:29 +03:00
esakemp 56d31fa496 bulk tag addition 2019-08-13 10:29:49 +03:00
Rochet2andGitHub ebea8ebdf8 Merge pull request #1251 from UniversityOfHelsinkiCS/trunk
Fix tests
2019-08-12 15:47:33 +03:00
Rochet2 b0ae6363de Retry fix unreliable tests 2019-08-12 15:14:08 +03:00
Rochet2 940c1c7670 Revert "Try fix unreliable tests"
This reverts commit 511451d4c6.
2019-08-12 15:13:12 +03:00
Rochet2 511451d4c6 Try fix unreliable tests 2019-08-12 14:15:23 +03:00
Rochet2 28e54f80d9 Hide ugly docker commands 2019-08-12 14:03:19 +03:00
esakemp 43d64ee99d Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-08-12 13:50:12 +03:00
esakemp 1f092dcbea small bug fix 2019-08-12 13:44:50 +03:00
Rochet2 34e6c84dd5 Merge branch 'trunk' of github.com:UniversityOfHelsinkiCS/oodikone into trunk 2019-08-12 13:35:39 +03:00
Rochet2 5677da70de Deprecate travis 2019-08-12 13:35:30 +03:00
Rochet2andGitHub f0d42f50a9 Merge pull request #1249 from UniversityOfHelsinkiCS/trunk
Circleci, tag minthification
2019-08-12 13:32:23 +03:00
esakemp f57835919d add confirm window when deleting tag from studyprogramme 2019-08-12 13:06:54 +03:00
esakemp 5e44b59575 Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-08-12 12:39:51 +03:00
esakemp 5f0946fa12 tag deletion fix, get rid of usage service spam 2019-08-12 12:39:32 +03:00
Rochet2 0cc3d5ac20 progress! 2019-08-12 12:30:38 +03:00
Rochet2 1e9face1a9 Merge branch 'trunk' of github.com:UniversityOfHelsinkiCS/oodikone into trunk 2019-08-12 12:09:14 +03:00
Rochet2andGitHub 0a9ec926df Update .travis.yml 2019-08-12 12:06:43 +03:00
Rochet2andGitHub 294ee913a4 Update .travis.yml 2019-08-12 11:51:37 +03:00
Rochet2andGitHub f2061c1d4d Revert oodi key (not used for circleci) 2019-08-12 11:39:57 +03:00
Rochet2andGitHub ac5f63fe66 Merge pull request #1247 from Rochet2/circleci
Circleci
2019-08-12 11:38:00 +03:00
Rochet2 84b7b96133 remove unused var 2019-08-12 11:36:44 +03:00
Rochet2 ab92381d19 Fix sentry versioning 2019-08-12 10:55:00 +03:00
esakemp 53e9faa843 tag addition minthification 2019-08-12 09:15:44 +03:00
esakempandGitHub c87868a731 Merge pull request #1242 from UniversityOfHelsinkiCS/trunk
Added multiselect to course statistics programme selection
2019-08-12 07:25:30 +03:00
Rochet2 37522fd9d8 test build speed 2019-08-11 21:26:41 +03:00
Rochet2 fd966f26da speedier CI build? 2019-08-11 21:23:07 +03:00
Rochet2 548ddbda53 Verify cypress before caching 2019-08-11 02:31:40 +03:00
Rochet2 27b7b984de Fix cypress commands 2019-08-11 01:18:49 +03:00
Rochet2 ab44f31646 Correct the env vars for production 2019-08-11 01:11:28 +03:00
Rochet2 0506572c4f Why is cypress still compressing?? 2019-08-11 01:06:29 +03:00
Rochet2andGitHub 7e7f728b28 Disable spamming logs with every request in CI 2019-08-10 17:19:10 +03:00
Rochet2 ea2f62c626 Remove duplicate logging 2019-08-10 15:02:34 +03:00
Rochet2 ac21eb9027 Background log? 2019-08-10 14:48:17 +03:00
Rochet2 d44b9ec704 Refactor circle conf 2019-08-10 14:38:39 +03:00
Rochet2 a6190c7836 Dont restart on crash in CI 2019-08-10 14:38:17 +03:00
Rochet2 a2dafd18de Fix more lint 2019-08-10 13:57:32 +03:00
Rochet2 239eaf6e02 fix lint? 2019-08-10 13:50:04 +03:00
Rochet2 b480189de8 Fix include path 2019-08-10 13:40:10 +03:00
Rochet2 4d6f38d6bc Try wait for DB to be ready before migrations 2019-08-10 13:31:42 +03:00
Rochet2andGitHub a31419f551 Update connection.js 2019-08-10 12:32:43 +03:00
Rochet2andGitHub 3bb9eef2e3 Update connection.js 2019-08-10 11:15:46 +03:00
Rochet2andGitHub e501fee4b5 Update index.js 2019-08-10 11:02:45 +03:00
Rochet2andGitHub 0b053684f3 Update connection.js 2019-08-10 11:01:24 +03:00
Rochet2andRochet2 026ea197e2 Update docker-compose.dev.real.yml 2019-08-10 03:25:47 +03:00
Rochet2andRochet2 a2649185dd Update docker-compose.dev.yml 2019-08-10 03:25:47 +03:00
Rochet2andRochet2 63b11a6ed6 Update docker-compose.yml 2019-08-10 03:25:47 +03:00
Rochet2andRochet2 ea4b970ddc Update config.yml 2019-08-10 03:25:47 +03:00
Rochet2 7f1bcbe302 faster build with one cache 2019-08-10 03:25:47 +03:00
Rochet2 762f3128f8 mixing it up 2019-08-10 03:25:47 +03:00
Rochet2 0f6d6864a0 enable release (remove false when finished) 2019-08-10 03:25:47 +03:00
Rochet2 29594c7e22 try optimize Dockerfiles 2019-08-10 03:25:47 +03:00
Rochet2andRochet2 64973cd929 Update config.yml 2019-08-10 03:25:47 +03:00
Rochet2andRochet2 ac6fc718cf Update config.yml 2019-08-10 03:25:47 +03:00
Rochet2 7b5871ed03 try fromcache 2019-08-10 03:25:47 +03:00
Rochet2andRochet2 02d9e7bd42 Update config.yml 2019-08-10 03:25:47 +03:00
Rochet2andRochet2 b53b6ee4af Update docker-compose.yml 2019-08-10 03:25:47 +03:00
Rochet2andRochet2 0863533894 Update docker-compose.lateste2e.yml 2019-08-10 03:25:47 +03:00
Rochet2andRochet2 52710dba85 Update config.yml 2019-08-10 03:25:47 +03:00
Rochet2andRochet2 3fc5d69ae2 Update config.yml 2019-08-10 03:25:47 +03:00
Rochet2andRochet2 18d8603647 Update config.yml 2019-08-10 03:25:47 +03:00
Rochet2andRochet2 8b22ff4204 Update config.yml 2019-08-10 03:25:47 +03:00
Rochet2 31f4578a96 never force push 2019-08-10 03:25:47 +03:00
Rochet2 aed866ddeb Try see videos 2019-08-10 03:25:47 +03:00
Rochet2 f0de025b7a parllel ism 2 2019-08-10 03:25:47 +03:00
Rochet2 ee903bd7e0 parllel ism 2019-08-10 03:25:47 +03:00
Rochet2 9441cb2ae3 jessus 2019-08-10 03:25:47 +03:00
Rochet2 1ef0e1eb31 jessus 2019-08-10 03:25:47 +03:00
Rochet2 36a4ea7984 jessus 2019-08-10 03:25:47 +03:00
Rochet2 8d66afab31 maybe fix something 2019-08-10 03:25:47 +03:00
Rochet2 c8aeb46ac0 maybe this? 2019-08-10 03:25:47 +03:00
Rochet2 8620fbe1c9 I have no idea 2019-08-10 03:25:47 +03:00
Rochet2 b7e5833361 fix cypress? 2019-08-10 03:25:47 +03:00
Rochet2 7de8913a67 asd 2019-08-10 03:25:47 +03:00
Rochet2 7fea8d73b1 circleci sux 2019-08-10 03:25:47 +03:00
Rochet2 f454bea449 apparently machine executor doesnt need this and errors out 2019-08-10 03:25:47 +03:00
Rochet2 caa4271640 apparently docker and machine have different formats 2019-08-10 03:25:47 +03:00
Rochet2 d98068944e apparently we cannot use volumes without this 2019-08-10 03:25:47 +03:00
Rochet2 454ee748c5 speed up build, fix nginx maybe 2019-08-10 03:25:47 +03:00
Rochet2 5c2d896742 ignore pull failures, fix filename 2019-08-10 03:25:47 +03:00
Rochet2 0f25ae9378 experiment with pull 2019-08-10 03:25:47 +03:00
Rochet2 7b078fb704 maybe fix nginx 2019-08-10 03:25:47 +03:00
Rochet2 92d98c24f5 add rest of script 2019-08-10 03:25:47 +03:00
Rochet2 0f6115fee0 learn how to use env variables in circleci 2019-08-10 03:25:47 +03:00
Rochet2 efb929989a try out stuff 2019-08-10 03:25:47 +03:00
Rochet2 73960c7ef4 move commands from scripts.sh to circleci config 2019-08-10 03:25:47 +03:00
Rochet2 546cbeb52a trigger build 2019-08-10 03:25:47 +03:00
Rochet2 7ce9f15c50 Use base64 encoding for OODI_KEY (not sure what the old scheme was) 2019-08-10 03:25:47 +03:00
Rochet2 c4e0db61e6 trigger circleci 2019-08-10 03:25:47 +03:00
Rochet2 a061f273f0 fix scripts.sh path 2019-08-10 03:25:47 +03:00
Rochet2 ef642ff813 initial circle ci push 2019-08-10 03:25:47 +03:00
Warro a899b05165 Updated texts to plural 2019-08-09 15:48:22 +03:00
Warro 024b68b80d Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-08-09 15:35:53 +03:00
Warro b0aa8c8ceb Added multiselect to course statistics programme selection 2019-08-09 15:35:46 +03:00
esakempandGitHub 3448ae44ab Merge pull request #1241 from UniversityOfHelsinkiCS/trunk
small fixes
2019-08-09 15:33:07 +03:00
esakemp f85b953995 fix warning 2019-08-09 15:17:18 +03:00
Rochet2 9e1bbe7269 remove class 2019-08-09 15:11:08 +03:00
esakemp 41cc2b43de more small fixes 2019-08-09 15:07:13 +03:00
esakemp e77d845583 smallest fix git push --no-verify 2019-08-09 14:57:05 +03:00
esakempandGitHub d3e0d7c6f9 Merge pull request #1240 from UniversityOfHelsinkiCS/trunk
fix-it-felix
2019-08-09 14:47:00 +03:00
Rochet2 391f201090 Remove % from progressbar 2019-08-09 14:38:50 +03:00
esakemp a287f1a70c fixing tags 2019-08-09 14:27:50 +03:00
esakemp ea4cb02d67 Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-08-09 13:49:00 +03:00
esakemp 9da9fdcbb2 some teacher fixes 2019-08-09 13:44:22 +03:00
Rochet2andGitHub 6998a5dc54 Merge pull request #1234 from UniversityOfHelsinkiCS/trunk
Refactor lodash, fix stop mocking
2019-08-09 13:42:33 +03:00
Rochet2 4c2a9b4750 Mistakes were made 2019-08-09 13:15:55 +03:00
Rochet2 7320d56955 Merge branch 'trunk' of github.com:UniversityOfHelsinkiCS/oodikone into trunk 2019-08-09 11:59:56 +03:00
Rochet2 04c883300e Try fix stop mocking 2019-08-09 11:59:47 +03:00
OlliandGitHub c2159a1762 Merge pull request #1230 from UniversityOfHelsinkiCS/trunk
Added loading bar to population and course statistics & some bug fixes
2019-08-09 11:02:59 +03:00
Warro 114ddddab0 Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-08-09 10:16:17 +03:00
esakemp 9be8243c2d peppe 2019-08-09 10:15:37 +03:00
Warro cb70b78445 Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-08-09 10:15:23 +03:00
Warro dda22c2b89 Added loading bar to course statistics 2019-08-09 10:15:16 +03:00
esakemp 801abb14ab lol fix 2019-08-09 10:10:03 +03:00
esakemp 6fe018f3bf fix tests so that shitty code goes through travis 2019-08-09 10:04:38 +03:00
esakemp cf54d58eda minthhhhhhhhh 2019-08-09 09:49:16 +03:00
Rochet2 fa8279100e Refactor lodash 2019-08-09 09:47:29 +03:00
esakemp a899ede2e2 leaderboard fixing 2019-08-09 09:32:48 +03:00
Rochet2 fba9462469 Merge branch 'trunk' of github.com:UniversityOfHelsinkiCS/oodikone into trunk 2019-08-09 09:08:58 +03:00
Rochet2andGitHub 41fd2f8f39 Rename services/oodikone2-frontend/src/components/Progressbar/progressBar.css to services/oodikone2-frontend/src/components/ProgressBar/progressBar.css 2019-08-09 09:05:36 +03:00
Rochet2andGitHub 5dcb9a39b1 Rename services/oodikone2-frontend/src/components/Progressbar/index.jsx to services/oodikone2-frontend/src/components/ProgressBar/index.jsx 2019-08-09 09:03:13 +03:00
Rochet2 dfd0de8e46 Merge branch 'trunk' of github.com:UniversityOfHelsinkiCS/oodikone into trunk 2019-08-08 17:02:34 +03:00
Rochet2 c2cfc79d40 Remove old code that does nothing 2019-08-08 16:58:06 +03:00
Rochet2 970f551808 Optimize Users page SQL query 2019-08-08 16:56:49 +03:00
Warro 77125f0e7d Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-08-08 15:14:22 +03:00
Warro 6e9b326e3a Added progress bar 2019-08-08 15:13:17 +03:00
Rochet2 aeff8850de Merge branch 'trunk' of github.com:UniversityOfHelsinkiCS/oodikone into trunk 2019-08-08 15:00:15 +03:00
Rochet2 404547e8dc remove deprecated token 2019-08-08 14:58:36 +03:00
Rochet2 07be51eab7 Move some papers around to look productive 2019-08-08 14:57:38 +03:00
esakemp c50871ff03 spin like a record 2019-08-08 14:23:38 +03:00
esakemp cc2dd275b1 fix jami bug again 2019-08-08 10:27:56 +03:00
esakempandGitHub d642899515 Merge pull request #1226 from UniversityOfHelsinkiCS/trunk
Add tests
2019-08-08 08:46:51 +03:00
Rochet2 1202303d10 Merge branch 'trunk' of github.com:UniversityOfHelsinkiCS/oodikone into trunk 2019-08-07 19:45:47 +03:00
Rochet2 30f66619d9 Try fix active status in updater 2019-08-07 19:45:38 +03:00
Rochet2andGitHub 9bebddc31c Merge branch 'master' into trunk 2019-08-07 19:38:18 +03:00
Rochet2 bddfc6208f Add back mandatory wait 2019-08-07 19:36:50 +03:00
Rochet2 242b9c962d Disable DB reset for cypress tests (was run for every test file) 2019-08-07 19:29:37 +03:00
Rochet2 bcd4f4f6cf Merge branch 'trunk' of github.com:UniversityOfHelsinkiCS/oodikone into trunk 2019-08-07 19:22:27 +03:00
Rochet2 dc2f15a2ae Wait for requests instead of set amount of seconds 2019-08-07 19:22:15 +03:00
Rochet2 b5e802707c Add new tests 2019-08-07 19:21:21 +03:00
Rochet2 3542cbefbe Reset DB before all cypress tests 2019-08-07 16:24:08 +03:00
Warro a18d48084e Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-08-07 15:37:31 +03:00
Warro b7f492e1b1 Fixed an issue where same 'update attainment dates' message was handled by all running writers 2019-08-07 15:37:27 +03:00
esakempandGitHub c3c960d9ca Merge pull request #1223 from UniversityOfHelsinkiCS/trunk
fixed teacher borking and added tests and refactored navbar
2019-08-07 14:57:02 +03:00
esakemp 3bea17bfbf Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-08-07 14:39:43 +03:00
esakemp 9df5340b55 DROPPING WAIT 2019-08-07 14:39:18 +03:00
Warro 802f73ee32 Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-08-07 14:27:40 +03:00
Warro e8542e6321 Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-08-07 14:16:11 +03:00
Warro a0440282e7 Refactored navbar 2019-08-07 14:16:03 +03:00
esakemp d408c58655 more tests 2019-08-07 14:12:32 +03:00
esakemp 796b8f77e1 maybe fix travis 2019-08-07 10:19:37 +03:00
esakemp 0a97185634 add tests to teacher page 2019-08-07 09:39:07 +03:00
esakemp da985ad7bb bug fixing 2019-08-07 09:07:40 +03:00
Rochet2andGitHub 2a3e42e3cc Merge pull request #1220 from UniversityOfHelsinkiCS/trunk
Fix transfers
2019-08-06 20:01:17 +03:00
Rochet2 39990fd704 Fix transfers 2019-08-06 19:41:20 +03:00
Rochet2andGitHub e3818b5112 Merge pull request #1219 from UniversityOfHelsinkiCS/trunk
Recode student list update
2019-08-06 19:07:35 +03:00
Rochet2 260d4b2c2a Merge branch 'trunk' of github.com:UniversityOfHelsinkiCS/oodikone into trunk 2019-08-06 18:46:35 +03:00
Rochet2 047523fd74 fix lint 2019-08-06 18:29:29 +03:00
Rochet2andGitHub d720221141 Merge branch 'master' into trunk 2019-08-06 18:26:58 +03:00
Rochet2 91209252cb Fix all out of sync sequences 2019-08-06 18:06:53 +03:00
Rochet2 b34f4603db Fix DB primary key sequence out of sync (whatever that is) 2019-08-06 17:55:11 +03:00
Rochet2 d924425877 Fix merge 2019-08-06 16:58:17 +03:00
OlliandGitHub 0af7333edc Merge pull request #1216 from UniversityOfHelsinkiCS/trunk
Backend bug fix and sentry improvement (or just more spam, remains to be seen)
2019-08-06 16:48:25 +03:00
Rochet2 3f9cbe187f Merge branch 'trunk' of github.com:UniversityOfHelsinkiCS/oodikone into trunk 2019-08-06 16:33:33 +03:00
Rochet2 6d3187fcca Remove old console logs, recode student list updating 2019-08-06 16:31:49 +03:00
Warro 646e68bb6a Added sentry error capturing for failed http requests with statuses 400 or 500 2019-08-06 16:24:26 +03:00
Warro 766bca0d57 Fixed backend route /v3/populationstatisticsbycourse error that was caused by missing body params 2019-08-06 15:37:51 +03:00
OlliandGitHub 1c7c1ddb9f Merge pull request #1212 from UniversityOfHelsinkiCS/trunk
Fixed 'laggy' auto submit search input
2019-08-06 14:51:12 +03:00
Warro 213bc8ef79 Fixed 'laggy' auto submit search input 2019-08-06 14:27:08 +03:00
esakempandGitHub 53175661d5 Merge pull request #1210 from UniversityOfHelsinkiCS/trunk
search history improvements and fixes
2019-08-06 13:59:35 +03:00
Warro 3341c2a8b8 Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-08-06 13:36:06 +03:00
esakemp f00f840965 small betterment 2019-08-06 12:40:06 +03:00
Warro 36aa16e42a Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-08-06 12:39:52 +03:00
esakemp a31ef078c3 Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-08-06 12:34:39 +03:00
Warro d2e7a2fb80 Fixed warning with duplicate keys in course stats 2019-08-06 12:32:14 +03:00
esakemp 647ab28a13 some searchhistory minttu 2019-08-06 12:28:17 +03:00
esakempandGitHub e9b0798e3e Merge pull request #1207 from UniversityOfHelsinkiCS/trunk
Fixed crash caused by opening nonexistent students
2019-08-06 11:38:50 +03:00
Warro 244b8c2132 Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-08-06 10:41:25 +03:00
Warro 8c07740c82 Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-08-06 10:12:49 +03:00
Warro 2c5d569684 Fixed a crash caused by trying to open a non-existent student 2019-08-06 10:12:40 +03:00
esakemp b4a17a2e9d add programme name to search history 2019-08-06 10:11:06 +03:00
Rochet2andGitHub 6a6fa123e4 Merge pull request #1204 from UniversityOfHelsinkiCS/trunk
Updater improvements
2019-08-05 20:06:21 +03:00
Rochet2andGitHub d30ea4aa47 Merge branch 'master' into trunk 2019-08-05 19:31:49 +03:00
Rochet2andGitHub b73a8abcd6 Fix lint 2/2 2019-08-05 19:31:32 +03:00
Rochet2andGitHub 326407ee27 Fix lint 1/2 2019-08-05 19:28:35 +03:00
Rochet2 fd0d4c42bc Merge branch 'trunk' of github.com:UniversityOfHelsinkiCS/oodikone into trunk 2019-08-05 18:56:56 +03:00
Rochet2 dabdae3e2f Improve updater 2019-08-05 18:56:34 +03:00
Rochet2andGitHub e19f632575 Merge pull request #1201 from UniversityOfHelsinkiCS/trunk
Drop element_details
2019-08-05 11:29:47 +03:00
esakemp 0870cc2d70 Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-08-05 10:13:51 +03:00
esakemp 63cb71021d deprecate useless shit 2019-08-05 10:08:58 +03:00
Rochet2 ceec3a8fd4 remove element_details from userservice 2019-08-05 10:08:47 +03:00
Rochet2 f78b2330ff new cron lib, this uses correct timezone properly 2019-08-04 11:30:47 +03:00
Rochet2 9874fce3f7 Try lock table to avoid deadlock, use single query for min and max attainment date update 2019-08-02 12:43:32 +03:00
Rochet2 e0ad826ddd Move schedule queue from in memory to nats (in memory is entirely lost on restart) 2019-08-02 10:58:50 +03:00
Rochet2 f894c34544 Add reschedule buttons to updater control panel 2019-08-01 23:56:13 +03:00
Rochet2 7457e2111a Fix updater meta api -> write message 2019-08-01 23:30:36 +03:00
Rochet2andGitHub 28566e4394 Merge pull request #1199 from UniversityOfHelsinkiCS/trunk
Updater improvements
2019-08-01 20:18:36 +03:00
Rochet2 a280aea3df Ack NO_STUDENT 2019-08-01 20:02:11 +03:00
Rochet2 539eab6586 Merge branch 'trunk' of github.com:UniversityOfHelsinkiCS/oodikone into trunk 2019-08-01 19:54:47 +03:00
Rochet2 c02145281f Updater control panel 5000000 2019-08-01 19:54:38 +03:00
OlliandGitHub 021040792c Merge pull request #1197 from UniversityOfHelsinkiCS/trunk
Population advanced settings bug fix
2019-08-01 16:23:48 +03:00
Warro e6306871e8 Fixed tests 2019-08-01 15:48:07 +03:00
Rochet2andGitHub fc037c77e1 Merge pull request #1195 from UniversityOfHelsinkiCS/trunk
Fix some axios shit
2019-08-01 14:39:09 +03:00
Warro 48a9bf7176 Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-08-01 14:27:09 +03:00
Warro 899b2504af fixedlint 2019-08-01 14:25:06 +03:00
Rochet2 e14f726890 Fix some axios shit 2019-08-01 14:18:27 +03:00
Warro 5c7820f540 Fixed an issue caused by qs sometimes parsing some query params as arrays and sometimes as strings, which broke the backend 2019-08-01 14:18:06 +03:00
Rochet2andGitHub 7a96900c57 Merge pull request #1193 from UniversityOfHelsinkiCS/trunk
Spinning
2019-08-01 13:18:17 +03:00
Rochet2 8f6c59260f Merge branch 'trunk' of github.com:UniversityOfHelsinkiCS/oodikone into trunk 2019-08-01 12:28:16 +03:00
Rochet2 b7ab052fda Adjust some of the cron dates not to overlap as much 2019-08-01 12:27:22 +03:00
esakemp d989a0b719 Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-08-01 11:57:18 +03:00
esakemp 1b08560d1d spinnnnnnnn 2019-08-01 11:57:05 +03:00
Rochet2andGitHub aac9901f3b Merge pull request #1192 from UniversityOfHelsinkiCS/trunk
Fixed course stats being overwritten by single course stats
2019-08-01 11:18:02 +03:00
Rochet2 85871a7f86 Merge branch 'trunk' of github.com:UniversityOfHelsinkiCS/oodikone into trunk 2019-08-01 10:57:33 +03:00
Rochet2 8b70b029a6 Updater fixes 2019-08-01 10:52:49 +03:00
Warro 73d2b1c546 Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-08-01 10:35:50 +03:00
Warro 5b3168660c Added reducer for single course stats so the course population doesn't overwrite all course stats 2019-08-01 10:20:35 +03:00
esakemp 7414418fa5 Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-08-01 08:59:30 +03:00
esakemp 3caea4edf8 lint 2019-08-01 08:52:10 +03:00
esakemp 83bc038581 filter fixing 2019-08-01 08:44:11 +03:00
Rochet2andGitHub 601fe30398 Merge pull request #1191 from UniversityOfHelsinkiCS/trunk
Search history for population and course stats
2019-07-31 16:23:55 +03:00
Rochet2 5aaffc5711 Fix limit and sort order 2019-07-31 16:06:11 +03:00
Rochet2 1c66dfd5d1 Merge branch 'trunk' of github.com:UniversityOfHelsinkiCS/oodikone into trunk 2019-07-31 15:56:27 +03:00
Rochet2 62acd788aa Fix typo that caused attainments never to be updated 2019-07-31 15:55:56 +03:00
Rochet2 a12c7b0f20 Change from string to json 2019-07-31 15:55:38 +03:00
Warro 7f62f10eda increased jest timeout in population tests 2019-07-31 15:05:09 +03:00
Warro ba0721f7fb Edited backend cron time 2019-07-31 15:00:33 +03:00
Warro 1b064b9b92 lint 2019-07-31 14:25:00 +03:00
Rochet2 3e49fa3434 Remove spammy log 2019-07-31 13:35:40 +03:00
Rochet2 e262f7d7f8 Fix the button 2019-07-31 13:32:58 +03:00
esakempandGitHub b9901f3135 Merge pull request #1189 from UniversityOfHelsinkiCS/trunk
fixing garbage
2019-07-31 13:32:15 +03:00
Warro f591850128 Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-31 13:23:29 +03:00
Warro b375b2c8e9 Addes search history to population search page 2019-07-31 13:22:42 +03:00
Rochet2 0b6fa1a201 Ignore all debug logs for git 2019-07-31 13:21:41 +03:00
esakemp 3c32f53827 more small bug fixes 2019-07-31 13:10:40 +03:00
esakemp 177fe931f2 shameful fix 2019-07-31 12:59:18 +03:00
Rochet2 17ad1bdd23 Add more logging to graylog 2019-07-31 12:58:55 +03:00
esakempandGitHub f241042e2f Merge pull request #1188 from UniversityOfHelsinkiCS/trunk
programme filter
2019-07-31 10:37:13 +03:00
Rochet2 bcb694330b Adjust AckWait for nats 2019-07-31 10:34:37 +03:00
esakemp 466dd1c68f programme filter 2019-07-31 10:13:54 +03:00
Warro 4e8a3360a5 Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-31 09:26:33 +03:00
Warro 0043be28c0 Refactored population search form component into functional component and edited the backend cron job to be a bit more chill with its requests to backend at once 2019-07-31 09:26:21 +03:00
Rochet2andGitHub ed265c70f9 Merge pull request #1185 from UniversityOfHelsinkiCS/trunk
Fix flaky test, Add a button, Remove compression, Record video always locally, Handle a new student status
2019-07-30 18:41:25 +03:00
Rochet2 862321da55 Compression, what is that? 2019-07-30 18:25:03 +03:00
Rochet2 5164b155aa Wait until page updates after changing filters 2019-07-30 18:15:41 +03:00
Rochet2 53b6b480b6 Locally always record a video in case of error 2019-07-30 18:12:18 +03:00
Rochet2 cf9420b758 Fix unknown status and simplify code 2019-07-30 17:25:02 +03:00
Rochet2 9cce15cf31 Add update oldest 2000 students button 2019-07-30 17:23:57 +03:00
Rochet2andGitHub cd3b6ace84 Merge pull request #1184 from UniversityOfHelsinkiCS/trunk
Updater api cache and sort data to try avoid deadlocks
2019-07-30 16:11:43 +03:00
Rochet2 4af5783dac Merge branch 'trunk' of github.com:UniversityOfHelsinkiCS/oodikone into trunk 2019-07-30 15:33:29 +03:00
Rochet2 5ec875cfc8 Fix tests for updater writer 2019-07-30 15:33:19 +03:00
esakemp ecefaf11a1 npm update 2019-07-30 15:20:09 +03:00
Rochet2 d32acd720e Merge branch 'trunk' of github.com:UniversityOfHelsinkiCS/oodikone into trunk 2019-07-30 15:16:54 +03:00
Rochet2 609fa4520d Try avoid deadlocks through sorting data 2019-07-30 15:16:40 +03:00
esakempandGitHub 9017925129 Merge pull request #1183 from UniversityOfHelsinkiCS/trunk
new amazing filter
2019-07-30 14:54:13 +03:00
Warro 66515d2f0c Added logic for saving search history and added search history for course search 2019-07-30 14:52:54 +03:00
esakemp bd0258b194 new amazing filter 2019-07-30 14:33:41 +03:00
Rochet2 40b7440123 Updater api cache to reduce oodi api request count 2019-07-30 14:01:06 +03:00
esakempandGitHub 9f65f9b55e Merge pull request #1182 from UniversityOfHelsinkiCS/trunk
filters for course populatoin
2019-07-30 12:59:13 +03:00
esakemp a99201dd21 Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-30 10:39:02 +03:00
esakemp 25c383957c course population filter stuff 2019-07-30 10:38:55 +03:00
Rochet2andGitHub 9c6cebf844 Merge pull request #1181 from UniversityOfHelsinkiCS/trunk
Pray that nats starts working
2019-07-30 10:38:26 +03:00
Rochet2 801c164a10 enforce always ack (before returned in some cases without ack) 2019-07-30 10:19:08 +03:00
Warro f54205a5ab Refactored course search to functional component 2019-07-30 10:18:09 +03:00
Rochet2andGitHub 98aaed44c9 Merge pull request #1180 from UniversityOfHelsinkiCS/trunk
Fix warnings, enable sentry plugin
2019-07-29 19:09:05 +03:00
Rochet2 d50e2cfcc4 fix convoluted retry logic 2019-07-29 19:04:01 +03:00
Rochet2 4826c8548f Merge branch 'trunk' of github.com:UniversityOfHelsinkiCS/oodikone into trunk 2019-07-29 18:49:26 +03:00
Rochet2 d002be556e Enable sentry plugin for uploading source maps and only upload if has tag or master build 2019-07-29 18:48:59 +03:00
Rochet2 c83ba786f6 Fix crash when teacher has no courses 2019-07-29 17:53:02 +03:00
Rochet2 89e63c6e35 Fix proptype warnings 2019-07-29 17:47:56 +03:00
Rochet2andGitHub 5cd2a16b24 Merge pull request #1178 from UniversityOfHelsinkiCS/trunk
Unified localization
2019-07-29 17:24:33 +03:00
Rochet2 b4745819fa Set proper versions to docker compose images 2019-07-29 17:22:17 +03:00
Warro 93e842dae6 vittusaatana 2019-07-29 17:09:16 +03:00
Warro ac03d0f8aa Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-29 16:53:15 +03:00
Warro 0a3cb0ef2e fixed tests vol2 2019-07-29 16:52:34 +03:00
Rochet2 741657d253 Fix lint 2019-07-29 16:48:09 +03:00
Rochet2 2ed6cf35fb Remove republishing 2019-07-29 16:37:09 +03:00
Rochet2 371e9b77b6 Fix cli 2019-07-29 16:31:55 +03:00
Rochet2 d7ad6b1804 Merge branch 'trunk' of github.com:UniversityOfHelsinkiCS/oodikone into trunk 2019-07-29 16:13:24 +03:00
Rochet2 84869f7f53 Comment out unused shuffle for eslint 2019-07-29 16:12:01 +03:00
Rochet2 4dcf3e1361 Updater: Disable durable due to issues, improve error handling, updatedAt now only for DONE, sort scheduled by oldest first 2019-07-29 16:09:04 +03:00
Warro 9ecec3aa54 Fixed tests 2019-07-29 15:14:09 +03:00
Rochet2 03386198cf Merge branch 'trunk' of github.com:UniversityOfHelsinkiCS/oodikone into trunk 2019-07-29 14:55:41 +03:00
Rochet2 be2565a565 Update dependency versions 2019-07-29 14:54:43 +03:00
Warro a1c0a91f31 Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-29 14:46:09 +03:00
Warro c861054749 Unified localization - before both state.settings.language and localize was randomly used 2019-07-29 14:46:03 +03:00
esakemp f7c8c86411 small bug fix 2019-07-29 09:07:19 +03:00
OlliandGitHub be2456ce3f Merge pull request #1169 from UniversityOfHelsinkiCS/trunk
Switched nats to cron in backend
2019-07-26 16:02:06 +03:00
Warro 0866981d18 fix lint 2019-07-26 15:38:58 +03:00
Warro d32890c2ce Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-26 15:37:07 +03:00
Warro e6e4cc68ab Removed nats from backend because scheduler doesn't run in production server and switched to node-cron instead 2019-07-26 15:36:59 +03:00
esakemp f1ab84b5c2 Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-26 14:34:53 +03:00
esakemp 5b17a7cf54 some more minttu 2019-07-26 14:34:35 +03:00
OlliandGitHub fd9d240cdb Merge pull request #1168 from UniversityOfHelsinkiCS/trunk
npm run lint to root and population jazz
2019-07-26 14:33:33 +03:00
Warro 9a755ad17b Fixed scripts 2019-07-26 14:12:07 +03:00
Warro d2744b6f1f Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-26 14:09:51 +03:00
Warro cde9da7333 Fixed travis 2019-07-26 14:09:40 +03:00
esakemp 7cd0a3463b Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-26 13:50:59 +03:00
esakemp f392947468 minthifying population of courestable 2019-07-26 13:50:50 +03:00
Warro 4a1e81a080 Added npm run lint to root that runs lint in all services & moved script files from root into the scripts folder 2019-07-26 13:35:57 +03:00
Rochet2 1e3f08495d Downgrade axios due to bug with defaults.params in latest version 2019-07-26 13:28:37 +03:00
Rochet2 84709afd4b Remove unused dependency 2019-07-26 13:14:58 +03:00
Rochet2 ac6da6af4e Remove analytics redis remnants 2019-07-26 13:00:24 +03:00
OlliandGitHub 0736d3e556 Merge pull request #1166 from UniversityOfHelsinkiCS/trunk
Faculty level stats and population of course stuff
2019-07-26 11:25:21 +03:00
esakemp c7da48a764 Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-26 11:13:17 +03:00
esakemp 55f75a6bcd make population of course look better 2019-07-26 11:13:11 +03:00
Rochet2 6a26d8a69a Merge branch 'trunk' of github.com:UniversityOfHelsinkiCS/oodikone into trunk 2019-07-26 11:05:43 +03:00
Rochet2 5fdad04a5e Fix lint errors 2019-07-26 11:03:08 +03:00
Warro 2b5bd33de9 Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-26 10:50:38 +03:00
Rochet2 74a9740c0a Add missing eslint configs to userservice 2019-07-26 10:44:55 +03:00
Warro 977dfb33fa fix lint 2019-07-26 10:41:25 +03:00
Rochet2 0ab859c40d Merge branch 'trunk' of github.com:UniversityOfHelsinkiCS/oodikone into trunk 2019-07-26 10:41:22 +03:00
esakemp cbc508bd94 warning fixes 2019-07-26 10:38:00 +03:00
Warro baa93f0840 Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-26 10:38:00 +03:00
Warro 88a86b0c92 Added 'Courses passed' and 'Courses failed' columns to faculties stat table and edited backend to return these values as well 2019-07-26 10:37:53 +03:00
esakemp fbb0f384da warning fix 2019-07-26 10:14:34 +03:00
esakemp b221bf255f lint pls 2019-07-26 09:56:51 +03:00
esakemp 8e21bf62f0 fixing stuff 2019-07-26 09:46:35 +03:00
esakemp 648624f0c0 population of course stuff wip 2019-07-26 08:32:18 +03:00
Rochet2 fdc7c62dbc Add lint to analytics and userservice 2019-07-25 19:14:47 +03:00
Rochet2andGitHub 85290eeca4 Merge pull request #1165 from UniversityOfHelsinkiCS/trunk
Fix tests and nats ack
2019-07-25 18:37:35 +03:00
Rochet2 b3b64c9f37 Try fix exit code calculation 2019-07-25 18:19:35 +03:00
Rochet2 3028210ec0 Reorder acks 2019-07-25 18:10:41 +03:00
Warro a6fb00628a Fixed test error 2019-07-25 16:21:17 +03:00
Warro 54fd6f4b0e Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-25 15:53:52 +03:00
Warro cce3fc68ad fixed lint errors 2019-07-25 15:53:48 +03:00
Warro 7edcaab4d3 Updated frontend to show faculty stats, added faculty stats to analytics DB, added cron job to update faculty stats 2019-07-25 15:11:24 +03:00
Rochet2andGitHub 9096673df6 Merge pull request #1164 from UniversityOfHelsinkiCS/trunk
Update dependencies, add linter, fix lint errors, add logging
2019-07-25 14:50:55 +03:00
Rochet2 40683e0596 Try fix updater scheduler tests 2019-07-25 14:42:34 +03:00
Rochet2 0865fdd8f2 temp disable updater scheduler lint 2019-07-25 14:36:39 +03:00
Rochet2 1d3838932e Fix lint rubbish 2019-07-25 14:13:54 +03:00
esakempandGitHub 7bcb7202e8 Merge pull request #1162 from UniversityOfHelsinkiCS/trunk
Population course improvements
2019-07-25 13:42:53 +03:00
Rochet2 f6962766ab Add lint to updater scheduler and api 2019-07-25 13:40:18 +03:00
Warro 70039c68ed Refactored code, added a lock just in case 2019-07-25 10:55:00 +03:00
Rochet2 f954939c3e Add logging back to updater 2019-07-25 10:54:48 +03:00
Rochet2 69af154a7e Merge branch 'trunk' of github.com:UniversityOfHelsinkiCS/oodikone into trunk 2019-07-25 10:25:49 +03:00
Rochet2 91549a0173 Update dependencies 2019-07-25 10:22:26 +03:00
Warro 423b0012d9 Edited faculty page, added endpoint to userservice for faculty programmes, added function that calculates yearly stats for faculty programmes 2019-07-25 10:17:33 +03:00
esakempandGitHub d377ac8607 cleaning 2019-07-25 10:00:11 +03:00
esakemp 4b63f4a55d population of course stuff 2019-07-25 09:48:15 +03:00
Rochet2andGitHub c6ffb23598 Merge pull request #1161 from UniversityOfHelsinkiCS/trunk
Sync updater
2019-07-24 17:43:10 +03:00
Rochet2 06353b6077 Merge branch 'trunk' of github.com:UniversityOfHelsinkiCS/oodikone into trunk 2019-07-24 16:57:27 +03:00
Rochet2 34389f7300 Make updater synchronous 2019-07-24 16:56:54 +03:00
Rochet2andGitHub 438ddb4078 Merge pull request #1160 from UniversityOfHelsinkiCS/trunk
Code improvements
2019-07-24 15:28:54 +03:00
esakemp 890282d0c8 oh shit 2019-07-24 15:13:35 +03:00
esakemp 78b0eb08f3 Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-24 15:01:18 +03:00
Rochet2 5e49fcd347 Increase updater DB connection count and connection aquire time 2019-07-24 14:54:42 +03:00
Rochet2 88de7ffa2f Improve updater error handling 2019-07-24 14:53:58 +03:00
Rochet2 d877c08d55 Fix updater writer tests and run them with all other tests 2019-07-24 14:52:07 +03:00
esakemp 4cec1253cc population of course stuff 2019-07-24 14:51:53 +03:00
esakemp 95bf452dde code improvements 2019-07-24 08:56:55 +03:00
Rochet2andGitHub b63daf263a Merge pull request #1157 from UniversityOfHelsinkiCS/trunk
Enable lint to backend and updater writer
2019-07-23 18:56:14 +03:00
Rochet2andGitHub f7efbbb009 Merge branch 'master' into trunk 2019-07-23 18:34:37 +03:00
Rochet2 1892fa2bfc Merge branch 'trunk' of github.com:UniversityOfHelsinkiCS/oodikone into trunk 2019-07-23 18:26:57 +03:00
Rochet2 079d45adba Enable lint to backend and updater writer, fix lint errors 2019-07-23 18:25:32 +03:00
esakempandGitHub a92d3ec382 Merge pull request #1156 from UniversityOfHelsinkiCS/trunk
Made oodikone error free again
2019-07-23 16:25:00 +03:00
Warro 274bba60b2 fixed cypress 2019-07-23 14:34:05 +03:00
Warro f28ee12df6 Fixed auth issue, apparently ErrorBoundary needs to be the one that dispatched the initial login action 2019-07-23 14:13:58 +03:00
Warro 09d0c1a7ff lint and clean code 2019-07-23 13:27:27 +03:00
Warro 5705aed715 Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-23 13:22:27 +03:00
Warro 3139f7e9f8 Fixed warnings caused by async componentdidmounts 2019-07-23 13:22:23 +03:00
esakempandGitHub 3cc825d029 Merge pull request #1155 from UniversityOfHelsinkiCS/trunk
Fix missing studentnumber
2019-07-23 13:14:02 +03:00
Rochet2 395fa176dc Fix missing studentnumber 2019-07-23 12:51:48 +03:00
esakempandGitHub 537963b702 Merge pull request #1154 from UniversityOfHelsinkiCS/trunk
Smart decisions were made
2019-07-23 11:41:27 +03:00
Rochet2 22e5f25afb updater logging 2019-07-23 11:18:30 +03:00
esakemp 1f26bc41b7 it was not smarter 2019-07-23 09:38:13 +03:00
esakemp 5517446c82 this is maybe bit smarter 2019-07-23 08:50:25 +03:00
esakempandGitHub b769b89e76 Merge pull request #1152 from UniversityOfHelsinkiCS/trunk
Fixed jest warning about open handles
2019-07-23 08:20:48 +03:00
Warro 978d0e5ee7 Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-22 15:39:54 +03:00
Warro 26f517fdff Closed some open handles that were left after backend jest tests 2019-07-22 15:39:50 +03:00
esakempandGitHub b6b3ef1f35 Merge pull request #1151 from UniversityOfHelsinkiCS/trunk
mluukkai and exterminator
2019-07-22 15:16:33 +03:00
esakemp a7da47a627 Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-22 14:52:14 +03:00
esakemp b38ba2b718 exterminator 2019-07-22 14:52:00 +03:00
Rochet2 2eed1bbfdc Merge branch 'trunk' of github.com:UniversityOfHelsinkiCS/oodikone into trunk 2019-07-22 14:00:13 +03:00
Rochet2 5da9cd5a81 Shorten mluukkai lifspan by 10 years 2019-07-22 14:00:03 +03:00
OlliandGitHub 3c2025206b Merge pull request #1148 from UniversityOfHelsinkiCS/trunk
Tables' styles seem be the worst thing that has ever happened to the human race
2019-07-22 13:33:29 +03:00
Warro fe0b8ea62f Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-22 12:41:23 +03:00
Warro b8b569f22b Added styles for a fixed header for tables 2019-07-22 12:41:15 +03:00
Rochet2andGitHub 1b441c2b2f Merge pull request #1147 from UniversityOfHelsinkiCS/trunk
Add logging to updater
2019-07-22 12:41:04 +03:00
Rochet2 f54631320b Add logging to updater 2019-07-22 12:27:15 +03:00
esakempandGitHub 7ff9c0c221 Merge pull request #1145 from UniversityOfHelsinkiCS/trunk
Warning!
2019-07-22 11:07:25 +03:00
Rochet2 73742a14ac Merge branch 'trunk' of github.com:UniversityOfHelsinkiCS/oodikone into trunk 2019-07-22 10:48:40 +03:00
Rochet2 6c87eab7b3 Prevent operations to different tables from interleaving in transaction to try reduce deadlocks 2019-07-22 10:37:04 +03:00
esakemp c6739c7b29 fix some wearnings 2019-07-22 10:19:02 +03:00
esakemp aed16d002a Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-22 09:21:23 +03:00
esakemp 87352db96c fix warning 2019-07-22 09:20:47 +03:00
Rochet2andGitHub 8bac62ed00 Merge pull request #1143 from UniversityOfHelsinkiCS/trunk
add time logging to updater writer
2019-07-22 09:20:18 +03:00
Rochet2 1d43c866f5 Merge branch 'trunk' of github.com:UniversityOfHelsinkiCS/oodikone into trunk 2019-07-22 09:06:24 +03:00
Rochet2 979b5f94e9 Disable sentry plugin for now (fails travis if sentry not up, maybe use cli instead) 2019-07-22 09:06:02 +03:00
esakemp ed2f040da9 Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-22 08:51:08 +03:00
esakemp ef65bb89d8 possible fix for low res screen 2019-07-22 08:51:01 +03:00
Rochet2 e83493d4a0 Add time logging for updater writer 2019-07-22 08:20:36 +03:00
Rochet2 b70d69c344 Remove retry 2019-07-22 08:06:14 +03:00
Rochet2andGitHub 38afeed262 Merge pull request #1142 from UniversityOfHelsinkiCS/trunk
Decrease suicide rate
2019-07-19 18:03:12 +03:00
Rochet2 95f0de7d91 Remove deprecated setting from sequelize conf 2019-07-19 17:34:02 +03:00
Rochet2 4ed4fa902f Merge branch 'trunk' of github.com:UniversityOfHelsinkiCS/oodikone into trunk 2019-07-19 17:30:09 +03:00
Rochet2 f53bbbd991 Try decrease deadlock suicide amount in updater 2019-07-19 17:29:35 +03:00
Rochet2andGitHub 5777497544 Merge pull request #1141 from UniversityOfHelsinkiCS/trunk
Fixed when passed, configure sentry releases
2019-07-19 11:02:19 +03:00
Warro dd19fcae7a Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-19 10:41:08 +03:00
Warro 196256b019 Deleted 20190710_00_delete_me_after_release.js migration 2019-07-19 10:39:05 +03:00
Rochet2 c0df532b02 Merge branch 'trunk' of github.com:UniversityOfHelsinkiCS/oodikone into trunk 2019-07-19 10:31:28 +03:00
Rochet2 fc30785cea Configure release version to sentry so source maps can be found from correct release 2019-07-19 10:30:58 +03:00
Warro 7392f026dc Fixed an issue in the student graph where tooltip of courses with same id only showed info about the first of those courses 2019-07-19 10:18:05 +03:00
esakemp f40caabf25 fixed 'when passed' course table in population statistics 2019-07-19 09:24:23 +03:00
esakempandGitHub 12324a0f25 Merge pull request #1140 from UniversityOfHelsinkiCS/trunk
Sentry, react-router and refactoring
2019-07-19 08:30:09 +03:00
Rochet2andGitHub 2cc4036cd8 Merge branch 'master' into trunk 2019-07-18 18:51:45 +03:00
Rochet2 9f23e19d18 Fix lint 2019-07-18 18:46:37 +03:00
Rochet2 46fbb9a604 Remove react-router as we use react-router-dom, update r-r-dom to fix proptype warning 2019-07-18 18:43:23 +03:00
Rochet2 597a96eb4d Merge branch 'trunk' of github.com:UniversityOfHelsinkiCS/oodikone into trunk 2019-07-18 18:14:10 +03:00
Rochet2 84f01d4568 Add sentry plugin to upload source maps 2019-07-18 18:13:49 +03:00
Warro 0044704d85 lint 2019-07-18 16:51:38 +03:00
esakempandGitHub 8e6491ba36 Merge pull request #1138 from UniversityOfHelsinkiCS/trunk
Game changing hook 🥊
2019-07-18 16:48:03 +03:00
Warro b18ec1446f refactored useTabs hook 2019-07-18 16:42:49 +03:00
Warro c8375bf6d8 Changed push to replace in useTabs hook because that's neater 2019-07-18 16:20:35 +03:00
Warro 3011fdbfed Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-18 16:05:24 +03:00
Warro bd95172927 ✨ LI-LI-LI-LINT ✨ 2019-07-18 16:05:17 +03:00
Warro 84e8481a81 Created hook useTabs that remembers which tab the user was using before a page reload and returns that tab 2019-07-18 15:44:32 +03:00
esakemp d41b24b867 fix 2019-07-18 15:37:26 +03:00
esakemp 28dfe0f4e0 oops fix 2019-07-18 15:01:31 +03:00
esakempandGitHub e68a79cb38 Merge pull request #1137 from UniversityOfHelsinkiCS/trunk
coursetable betterments and other trash
2019-07-18 14:53:29 +03:00
esakemp 15329f1d63 try to get 'when passed' to work 2019-07-18 13:51:47 +03:00
esakemp 798ad0f3f1 fix grade table to show number of failed instances 2019-07-18 11:03:07 +03:00
Rochet2 9477bcff9b Merge branch 'trunk' of github.com:UniversityOfHelsinkiCS/oodikone into trunk 2019-07-17 16:50:07 +03:00
Rochet2 a373d4f031 Fix backup download 2019-07-17 16:18:14 +03:00
esakemp 5ac1c082db Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-17 15:18:54 +03:00
esakemp c8f4266207 some backend trash 2019-07-17 15:18:44 +03:00
esakemp e4ee6089b0 improve student list check 2019-07-17 15:17:55 +03:00
OlliandGitHub d00e11e44b Merge pull request #1133 from UniversityOfHelsinkiCS/trunk
✨Improved graph ✨ & ❗️ERROR HANDLING ❗️
2019-07-17 14:54:35 +03:00
Warro a2f6fb6b80 Fixed an unhandled exception in updater that was thrown when the updater tried to fetch information about a student number which doesn't exist in oodi 2019-07-17 14:34:44 +03:00
Warro 5dc739aed3 Added possibility to see tooltips over overlapping courses in student statistics by hovering the cursor over the target point 2019-07-17 10:17:48 +03:00
Rochet2andGitHub 04bb80a6ec Merge pull request #1132 from UniversityOfHelsinkiCS/trunk
Minor bug fixes 🦟👏 and a migration 🧨
2019-07-16 19:41:46 +03:00
Warro 7f3e84af31 Added a migration that drops mandatory_course_labels from backend DB 2019-07-16 16:35:03 +03:00
Warro fb3abe5b45 ✨ LINT ✨ 2019-07-16 16:01:59 +03:00
Warro 74ea8942de Added the dispatchment of clearCourseStats to componentDidMount of course statistics search form, because course statistic didn't fetch new course if back button was used 2019-07-16 15:54:13 +03:00
Warro 064bb9eee2 Fixed an error where student page crashed if the student had zero courses marked 2019-07-16 15:09:57 +03:00
Tuomo TorppaandGitHub 46560ab421 Merge pull request #1129 from UniversityOfHelsinkiCS/trunk
Beautiful stidutrack improbement intelligent system and removed some npm packages
2019-07-16 14:57:00 +03:00
Warro db5c2f900e Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-16 14:34:37 +03:00
Warro 24d315f6b5 linted linter lint mint 2019-07-16 14:34:32 +03:00
Tuomo Torppa b8271cf8a5 Beautiful stidutrack improbement intelligent system 2019-07-16 14:26:54 +03:00
Warro 79fb0496fa removed npm packages highcharts-react-official and recharts from use, made AccessDenied page responsive ✨ 2019-07-16 14:08:19 +03:00
Warro 402697eb36 refactored multicolor barchart to use highcharts instead of recharts 2019-07-16 13:43:45 +03:00
esakempandGitHub b83d87a4c8 Merge pull request #1125 from UniversityOfHelsinkiCS/trunk
Replaced recharts with highcharts in student page
2019-07-16 13:18:27 +03:00
Warro 2f5179cdcc Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-16 12:48:29 +03:00
esakemp 46154cfbba oops 2019-07-16 12:47:44 +03:00
Warro 7122dde6b0 Made reference line more precise 2019-07-16 12:44:17 +03:00
Warro 3b38e0edd2 Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-16 12:41:02 +03:00
Warro 3045a1cb2f Deleted old credit accumulation graph 2019-07-16 12:34:11 +03:00
Warro fbb8a82984 Replaced credit accumulation graph in student details page with highcharts graph 2019-07-16 12:10:45 +03:00
esakemp 8b09f4b56c fixed jami bug 2019-07-16 12:08:04 +03:00
esakemp 92cefe86b7 remove duplicate courses from studenttable 2019-07-16 09:38:09 +03:00
Rochet2 10f8932f2d Fix cypress test 2019-07-15 15:00:00 +03:00
esakempandGitHub 078217de20 Merge pull request #1118 from UniversityOfHelsinkiCS/trunk
shameful pull request
2019-07-15 12:22:26 +03:00
esakemp 1900c6f8bb maybe it works now 2019-07-15 11:58:31 +03:00
esakempandGitHub b34d04bc56 Merge pull request #1117 from UniversityOfHelsinkiCS/trunk
fix own garbage
2019-07-15 10:56:32 +03:00
esakemp 7138e46214 was this even needed 2019-07-15 10:41:03 +03:00
esakemp d029460fa1 totally useless stuff deleted 2019-07-15 09:53:28 +03:00
esakemp 6346a8d42c Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-15 09:37:15 +03:00
esakemp 7d5aabb12b minor fidx 2019-07-15 09:31:05 +03:00
esakemp c52e6bc738 fix warnings and betterify population refecth 2019-07-15 09:11:24 +03:00
esakemp a1a458bd4b fix some warnings 2019-07-15 08:32:18 +03:00
esakempandGitHub cb617bbaa7 Merge pull request #1116 from UniversityOfHelsinkiCS/trunk
got rid of recalculate course table button and fixed **everything**
2019-07-15 08:07:49 +03:00
Warro 66d45cd8c9 vitun lint 2019-07-12 16:41:43 +03:00
Warro 4b2d14e464 vitun progress bar 2019-07-12 15:59:25 +03:00
Warro 3300f397dc Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-12 15:36:16 +03:00
Warro d744c6e3f8 Fixed cypress tests, added lock to backend, fixed a bug caused by discipline type filter 2019-07-12 15:36:11 +03:00
Rochet2 6eb663d83a erge branch 'trunk' of github.com:UniversityOfHelsinkiCS/oodikone into trunk 2019-07-12 15:24:05 +03:00
Rochet2 75e8283c77 Fix migration missing table 2019-07-12 14:33:01 +03:00
esakemp c0ad24f113 even minorer fix 2019-07-12 12:01:22 +03:00
esakemp 456e20dac5 minor fixes 2019-07-12 11:47:38 +03:00
esakemp 10424d7a15 no need to refetch population data thats already in store 2019-07-12 10:41:56 +03:00
Warro 6f6e67c2bd got rid of recalculate course table button 2019-07-12 10:18:24 +03:00
Warro a03b00f3b8 removed unnecessary imports 2019-07-11 16:05:19 +03:00
Sasu MäkinenandGitHub 25b8a5d27a Merge pull request #1114 from UniversityOfHelsinkiCS/trunk
O P T I M I Z E
2019-07-11 15:52:59 +03:00
esakemp c8f41413b7 Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-11 15:11:58 +03:00
esakemp cd23e8b970 amazing optimization 2019-07-11 15:06:48 +03:00
Warro b6bf75f837 Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-11 11:51:59 +03:00
Warro caa97402d6 Fixed overview cypress test 2019-07-11 11:51:54 +03:00
esakempandGitHub ddf1fedcbc Merge pull request #1111 from UniversityOfHelsinkiCS/trunk
merge pull request, fac, cypress is the worst
2019-07-11 11:44:25 +03:00
esakemp 1a1de69478 ... 2019-07-11 10:42:49 +03:00
esakemp 9d224caa33 revert fac back 2019-07-11 10:40:36 +03:00
esakemp bd757f20eb GIT PUSH NO VERIFY 2019-07-11 10:36:38 +03:00
esakemp 029f719679 WORK ALREADY FFS 2019-07-11 10:22:12 +03:00
esakemp 5c9f5d8b30 fixing cypress 2019-07-11 10:01:29 +03:00
esakemp db9e3eb16c Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-11 09:21:44 +03:00
esakemp 0c307b47ee add test for jumping to population from student 2019-07-11 09:03:06 +03:00
esakempandGitHub 77517edfe5 Merge pull request #1107 from UniversityOfHelsinkiCS/dependabot/npm_and_yarn/services/oodikone2-frontend/trunk/lodash-4.17.13
[Security] Bump lodash from 4.17.11 to 4.17.13 in /services/oodikone2-frontend
2019-07-11 09:02:05 +03:00
esakempandGitHub c127a2ba50 Merge pull request #1108 from UniversityOfHelsinkiCS/dependabot/npm_and_yarn/services/updater_api/trunk/lodash-4.17.13
[Security] Bump lodash from 4.17.11 to 4.17.13 in /services/updater_api
2019-07-11 09:01:58 +03:00
esakempandGitHub f2c77d52c7 Merge pull request #1109 from UniversityOfHelsinkiCS/dependabot/npm_and_yarn/services/updater_scheduler/trunk/lodash-4.17.14
[Security] Bump lodash from 4.17.11 to 4.17.14 in /services/updater_scheduler
2019-07-11 09:01:50 +03:00
esakempandGitHub 94d9120446 Merge pull request #1104 from UniversityOfHelsinkiCS/dependabot/npm_and_yarn/services/oodikone2-analytics/trunk/lodash-4.17.13
[Security] Bump lodash from 4.17.11 to 4.17.13 in /services/oodikone2-analytics
2019-07-11 09:01:42 +03:00
esakempandGitHub 1878f1c7ef Merge pull request #1105 from UniversityOfHelsinkiCS/dependabot/npm_and_yarn/services/backend/updater_writer/trunk/lodash-4.17.14
[Security] Bump lodash from 4.17.11 to 4.17.14 in /services/backend/updater_writer
2019-07-11 09:01:34 +03:00
esakempandGitHub 58867cba05 Merge pull request #1106 from UniversityOfHelsinkiCS/dependabot/npm_and_yarn/services/backend/oodikone2-backend/trunk/lodash-4.17.13
[Security] Bump lodash from 4.17.11 to 4.17.13 in /services/backend/oodikone2-backend
2019-07-11 09:01:03 +03:00
dependabot-preview[bot]andGitHub 8a9bb738ff [Security] Bump lodash in /services/backend/oodikone2-backend
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.11 to 4.17.13. **This update includes security fixes.**
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.11...4.17.13)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-07-11 05:24:48 +00:00
dependabot-preview[bot]andGitHub 7b4f0e1d6f [Security] Bump lodash in /services/oodikone2-frontend
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.11 to 4.17.13. **This update includes security fixes.**
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.11...4.17.13)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-07-11 05:24:46 +00:00
dependabot-preview[bot]andGitHub d8e9f06271 [Security] Bump lodash in /services/backend/updater_writer
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.11 to 4.17.14. **This update includes security fixes.**
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.11...4.17.14)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-07-11 05:24:34 +00:00
dependabot-preview[bot]andGitHub 8b73732a3a [Security] Bump lodash in /services/updater_scheduler
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.11 to 4.17.14. **This update includes security fixes.**
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.11...4.17.14)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-07-11 05:24:33 +00:00
dependabot-preview[bot]andGitHub 8a7fd122ec [Security] Bump lodash from 4.17.11 to 4.17.13 in /services/updater_api
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.11 to 4.17.13. **This update includes security fixes.**
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.11...4.17.13)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-07-11 05:24:32 +00:00
dependabot-preview[bot]andGitHub e29c48a41a [Security] Bump lodash in /services/oodikone2-analytics
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.11 to 4.17.13. **This update includes security fixes.**
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.11...4.17.13)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-07-11 05:24:01 +00:00
esakempandGitHub c549ed5b49 Merge pull request #1103 from UniversityOfHelsinkiCS/dependabot/npm_and_yarn/services/oodikone2-userservice/trunk/lodash-4.17.14
[Security] Bump lodash from 4.17.11 to 4.17.14 in /services/oodikone2-userservice
2019-07-11 08:23:19 +03:00
dependabot-preview[bot]andGitHub bcb898430c [Security] Bump lodash in /services/oodikone2-userservice
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.11 to 4.17.14. **This update includes security fixes.**
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.11...4.17.14)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-07-11 05:23:06 +00:00
esakempandGitHub d53de639cf Merge pull request #1102 from UniversityOfHelsinkiCS/dependabot/npm_and_yarn/services/backend/oodikone2-backend/trunk/lodash.merge-4.6.2
[Security] Bump lodash.merge from 4.6.1 to 4.6.2 in /services/backend/oodikone2-backend
2019-07-11 08:22:47 +03:00
esakempandGitHub b63e05a1ac Merge pull request #1101 from UniversityOfHelsinkiCS/dependabot/npm_and_yarn/services/oodikone2-frontend/trunk/lodash-es-4.17.14
[Security] Bump lodash-es from 4.17.11 to 4.17.14 in /services/oodikone2-frontend
2019-07-11 08:22:39 +03:00
esakempandGitHub 83085b7076 Merge pull request #1100 from UniversityOfHelsinkiCS/dependabot/npm_and_yarn/services/oodikone2-frontend/trunk/lodash.mergewith-4.6.2
[Security] Bump lodash.mergewith from 4.6.1 to 4.6.2 in /services/oodikone2-frontend
2019-07-11 08:22:19 +03:00
esakempandGitHub 1e7f52a5d2 Merge pull request #1110 from UniversityOfHelsinkiCS/dependabot/npm_and_yarn/services/oodikone2-usageservice/trunk/lodash-4.17.13
[Security] Bump lodash from 4.17.11 to 4.17.13 in /services/oodikone2-usageservice
2019-07-11 08:21:35 +03:00
dependabot-preview[bot]andGitHub 025cef6636 [Security] Bump lodash in /services/oodikone2-usageservice
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.11 to 4.17.13. **This update includes security fixes.**
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.11...4.17.13)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-07-11 01:19:48 +00:00
dependabot-preview[bot]andGitHub 0f44b9e338 [Security] Bump lodash.merge in /services/backend/oodikone2-backend
Bumps [lodash.merge](https://github.com/lodash/lodash) from 4.6.1 to 4.6.2. **This update includes security fixes.**
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-07-10 20:53:01 +00:00
dependabot-preview[bot]andGitHub baea6bab34 [Security] Bump lodash-es in /services/oodikone2-frontend
Bumps [lodash-es](https://github.com/lodash/lodash) from 4.17.11 to 4.17.14. **This update includes security fixes.**
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.11...4.17.14)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-07-10 20:50:35 +00:00
dependabot-preview[bot]andGitHub 9617bc4d97 [Security] Bump lodash.mergewith in /services/oodikone2-frontend
Bumps [lodash.mergewith](https://github.com/lodash/lodash) from 4.6.1 to 4.6.2. **This update includes security fixes.**
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-07-10 20:50:08 +00:00
Rochet2andGitHub c8f038f093 Merge pull request #1098 from UniversityOfHelsinkiCS/trunk
rounding, scheduleMeta and hide progress bar
2019-07-10 16:31:41 +03:00
Rochet2 c5b1f5fdf2 Merge branch 'trunk' of github.com:UniversityOfHelsinkiCS/oodikone into trunk 2019-07-10 16:12:49 +03:00
Rochet2 fd3d7f51c0 Drop unused old table ldapuser 2019-07-10 16:01:55 +03:00
Rochet2 51d809135d Trunkate broken migrations 2019-07-10 16:01:40 +03:00
Mäkinen Sasu S cab98792dc perlerkelrek 2019-07-10 15:55:21 +03:00
Mäkinen Sasu S 4ec3ba2706 HIDE PROGRESS BAR ABOMINATION 2019-07-10 15:35:36 +03:00
Mäkinen Sasu S 10825afe66 Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-10 15:29:47 +03:00
Mäkinen Sasu S ff4afa6649 npm run scheduleMeta 2019-07-10 15:29:35 +03:00
esakempandGitHub dbf480acf6 Merge pull request #1097 from UniversityOfHelsinkiCS/trunk
Made oodikone impenetrable security wise
2019-07-10 15:01:48 +03:00
Warro aeb2445921 Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-10 14:57:21 +03:00
Warro 431fedb2ee Fixed rounding in teacher statistics 2019-07-10 14:53:08 +03:00
esakemp 943e22b7e9 Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-10 14:48:15 +03:00
Tuomo TorppaandGitHub 6b0d4d1d42 Merge branch 'master' into trunk 2019-07-10 14:45:00 +03:00
esakemp 11a7fbd42e Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-10 14:44:00 +03:00
esakemp 43795aa4e6 fac updater fix 2019-07-10 14:43:55 +03:00
Rochet2 86b1aa1a39 Merge branch 'trunk' of github.com:UniversityOfHelsinkiCS/oodikone into trunk 2019-07-10 14:30:41 +03:00
Rochet2 23bedc7fc1 Fix transferred calculations, use DB data instead of deducing during runtime 2019-07-10 14:30:32 +03:00
Warro ba11d52fd3 Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-10 14:21:30 +03:00
Tuomo Torppa 2b5696a1b0 Incredible transition from student page to population stats 2019-07-10 14:12:47 +03:00
Warro 8b1947c5ee Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-10 14:09:26 +03:00
Warro 4357346995 Check user access rights from db instead of token 2019-07-10 14:09:21 +03:00
esakemp b10f51de28 Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-10 13:37:57 +03:00
esakemp bcbb2fb0ff deprecate settings 2019-07-10 13:37:27 +03:00
Mäkinen Sasu S b9b19d2624 if monday return 2019-07-10 13:30:34 +03:00
Mäkinen Sasu S 671d7e774f Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-10 13:23:40 +03:00
Rochet2andGitHub a37571a19b Merge pull request #1096 from UniversityOfHelsinkiCS/trunk
only the most epic of loading bars and possibly fixing shit
2019-07-10 13:18:09 +03:00
esakemp 108e756965 Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-10 11:35:07 +03:00
Rochet2 413b4ddd89 Merge branch 'trunk' of github.com:UniversityOfHelsinkiCS/oodikone into trunk 2019-07-10 10:40:24 +03:00
Tuomo Torppa 1554ef22f4 The finest progress bar you've ever seen (in oodikone) 2019-07-10 09:43:26 +03:00
Mäkinen Sasu S 8a0e130a22 some handling to /updatedatabase 2019-07-10 09:22:25 +03:00
esakemp ec6bd208e2 tmep fix for fac mabe 2019-07-10 09:14:21 +03:00
Rochet2 01826b9d0c Merge branch 'trunk' of github.com:UniversityOfHelsinkiCS/oodikone into trunk 2019-07-09 15:26:53 +03:00
Sasu MäkinenandGitHub 22ea7357d6 Merge pull request #1092 from UniversityOfHelsinkiCS/trunk
true -> !true
2019-07-09 14:49:44 +03:00
Mäkinen Sasu S b9d5ef6867 false -> true 2019-07-09 14:36:40 +03:00
Mäkinen Sasu S 837b39a906 true -> false 2019-07-09 14:35:21 +03:00
Sasu MäkinenandGitHub 55c97c7252 Merge pull request #1089 from UniversityOfHelsinkiCS/trunk
Bug when clearing comparison group in course statistic when "All" selected
2019-07-09 14:00:56 +03:00
Mäkinen Sasu S b4f47179e0 Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-09 13:33:01 +03:00
Mäkinen Sasu S b34fd78f57 prirpripripr 2019-07-09 13:32:53 +03:00
esakemp efd59c4a1f Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-09 13:17:05 +03:00
esakemp 4082e6e7ae fix tagz 2019-07-09 13:16:53 +03:00
Rochet2 c756f115bd Merge branch 'trunk' of github.com:UniversityOfHelsinkiCS/oodikone into trunk 2019-07-09 13:15:46 +03:00
Warro 59c253d3e2 Fixed issue where clearing 'ALL' option from comparison group in course statistic didn't clear the dropdown input 2019-07-09 12:58:09 +03:00
Rochet2 29015cab47 Merge branch 'trunk' of github.com:UniversityOfHelsinkiCS/oodikone into trunk 2019-07-09 12:37:16 +03:00
Sasu MäkinenandGitHub d28dcfa374 Merge pull request #1083 from UniversityOfHelsinkiCS/trunk
Refactored Travis to only do one build per push and other mayhem
2019-07-09 11:24:00 +03:00
Warro 464733fcc0 fixed another syntax error in .travis.yml 2019-07-09 10:51:10 +03:00
Warro 80740e53e7 fixed syntax error in .travis.yml 2019-07-09 10:48:24 +03:00
Warro 0e2134874f changed prod to latest 2019-07-09 10:45:01 +03:00
Warro aa6fdd34e9 fixed typo 2019-07-09 10:41:47 +03:00
Warro 0c4c75d45b Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-09 10:41:16 +03:00
Warro 97b48da7cf Combined stages so that data can be shared in different deploy stages 2019-07-09 10:41:13 +03:00
esakemp a9e8ed4d66 Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-09 10:24:47 +03:00
Warro 54308c7dce Added stages to travis 2019-07-09 10:22:56 +03:00
esakemp 8c504775cd Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-09 10:21:11 +03:00
esakemp 67bcce5fd4 bck bttn wrk 2019-07-09 10:17:19 +03:00
Warro 50f62e556a Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-09 10:02:33 +03:00
Warro 94fee52817 Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-09 09:50:09 +03:00
Warro 3f8b4746c2 Refactored Travis so that it only does one build 2019-07-09 09:48:51 +03:00
Mäkinen Sasu S 3b41db701e add transaction lock to updating attainment meta so it wont crash on deadlock 2019-07-09 09:45:56 +03:00
Mäkinen Sasu S dafa5561a4 rm volumes from default backend dco conf 2019-07-08 17:25:29 +03:00
Mäkinen Sasu S 2598f54dea fix subscription functions to await 2019-07-08 16:55:45 +03:00
Mäkinen Sasu S 2c06cd5295 fix travis typo 2019-07-08 16:34:05 +03:00
Mäkinen Sasu S 810a3fd689 mergele 2019-07-08 15:45:40 +03:00
Mäkinen Sasu S e7db17d766 update students on demand supporrtt 2019-07-08 15:43:28 +03:00
Tuomo Torppa 95d5bb5a93 Sad push of non-implement course page - population 2019-07-08 15:38:43 +03:00
Mäkinen Sasu S 11feb61e2d mergeleyst 2019-07-08 14:38:25 +03:00
Mäkinen Sasu S b1245da77c systems 2019-07-08 14:35:47 +03:00
esakempandGitHub b1ea23a296 Merge pull request #1082 from UniversityOfHelsinkiCS/trunk
Use extend in travis docker-compose files
2019-07-08 14:35:35 +03:00
Warro 68df47a04d Removed volume usageservice in docker-compose root file 2019-07-08 14:00:12 +03:00
Warro b1b863af00 Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-08 13:23:14 +03:00
Warro 477e39d38d Use extend in travis docker-compose files 2019-07-08 13:22:21 +03:00
esakemp f1df5630d4 lol sasu 2019-07-08 10:28:06 +03:00
Rochet2andGitHub c5cc7bd9e8 Merge pull request #1079 from UniversityOfHelsinkiCS/trunk
Started using extending in docker compose files
2019-07-05 17:43:31 +03:00
Warro aca042401f Reverted all commits, will be back on it on monday 2019-07-05 16:27:00 +03:00
Warro a93e77c2ec fixing travis........................................................... 2019-07-05 16:15:01 +03:00
Warro f0835e6f19 fixing travis........................................................... 2019-07-05 16:06:18 +03:00
Warro ef9bec9a8e fixing travis........................................................... 2019-07-05 15:54:24 +03:00
Rochet2 9dc27cf530 Fix updater writer db url in real data 2019-07-05 15:24:37 +03:00
Warro a07b59bce9 fixing travis.................................................. 2019-07-05 15:15:43 +03:00
Warro f059a7acd4 fixing travis............................................... 2019-07-05 15:14:52 +03:00
Warro 593ecffe73 fixing travis..................................... 2019-07-05 15:01:10 +03:00
Warro d83e0fc4d6 fixing travis........................ 2019-07-05 14:52:57 +03:00
Rochet2 2183086c2b Merge branch 'trunk' of github.com:UniversityOfHelsinkiCS/oodikone into trunk 2019-07-05 14:48:47 +03:00
Rochet2 f6c84a712f Fix transfers table constraints 2019-07-05 14:48:02 +03:00
Warro 3fa5c5f1d8 fixing travis................ 2019-07-05 14:33:50 +03:00
Warro 53791bc049 fixing travis.... 2019-07-05 14:22:04 +03:00
Warro 45e2ec6948 fixing travis 2019-07-05 14:03:35 +03:00
Warro 4af70bd148 fixing travis 2019-07-05 13:37:58 +03:00
Sasu MäkinenandGitHub 12e945db4d Merge pull request #1078 from UniversityOfHelsinkiCS/trunk
UVANJ MK;.
2019-07-05 12:48:57 +03:00
Warro 7528b9a028 Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-05 12:38:31 +03:00
Warro edf0f9032c Use extend in travis docker-compose files 2019-07-05 12:38:25 +03:00
Mäkinen Sasu S b11e508e00 umzugvittu 2019-07-05 12:35:38 +03:00
Mäkinen Sasu S 72ceb15b46 Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-05 12:16:32 +03:00
Mäkinen Sasu S 64b3ac47d6 improt mzung 2019-07-05 12:16:11 +03:00
esakemp a78b0d1b79 fix warning in coursetable 2019-07-05 11:55:27 +03:00
Sasu MäkinenandGitHub f358d176a6 Merge pull request #1076 from UniversityOfHelsinkiCS/trunk
Access token to redux and other minor doodoo
2019-07-05 11:27:47 +03:00
Mäkinen Sasu S b54409167e fix test with wait lol 2019-07-05 11:04:41 +03:00
Mäkinen Sasu S 7fb1ee4e32 npm i umzug in updater writer 2019-07-05 09:41:02 +03:00
Warro a1adbf2051 Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-05 09:04:41 +03:00
esakemp c902d7dbe4 fix warning in overview 2019-07-05 08:27:23 +03:00
esakemp 63a8f266c1 fix year selection for mozilla and possibly other browsers 2019-07-05 08:06:48 +03:00
Sasu MäkinenandGitHub 3253a178e9 Merge pull request #1075 from UniversityOfHelsinkiCS/trunk
MInthify dropdown favicon migrations
2019-07-04 17:42:45 +03:00
Mäkinen Sasu S 3e4e01216a migrations to writer 2019-07-04 17:22:19 +03:00
Mäkinen Sasu S d0fd7ef5a6 favicon 2019-07-04 17:06:13 +03:00
Warro 693be809e1 Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-04 16:51:05 +03:00
Warro 39b0c1b7d1 Added access token to redux 2019-07-04 16:50:33 +03:00
esakemp 03799a5746 minthify coursepage dropdown numbers 2019-07-04 15:16:53 +03:00
esakempandGitHub c7711db1c1 Merge pull request #1074 from UniversityOfHelsinkiCS/trunk
Esakkkkempppa
2019-07-04 12:52:22 +03:00
Mäkinen Sasu S 560c82907a revert scheduler to old life 2019-07-04 12:17:02 +03:00
esakemp 4dc62507f8 fix unmatching numbers maybe 2019-07-04 10:00:00 +03:00
Rochet2andGitHub 05de857989 Merge pull request #1070 from UniversityOfHelsinkiCS/trunk
Changed pg_restore commands to use docker instead and edited ping_psq…
2019-07-03 20:37:27 +03:00
Rochet2 c91d633b8f add missing table 2019-07-03 18:40:46 +03:00
Rochet2 085f578caf Merge branch 'trunk' of github.com:UniversityOfHelsinkiCS/oodikone into trunk 2019-07-03 18:26:36 +03:00
Rochet2 3eb04f5901 Remove unused stuff, fix db_kone fullsetup 2019-07-03 18:26:19 +03:00
Rochet2andGitHub 3144e52a5a Merge branch 'master' into trunk 2019-07-03 17:54:44 +03:00
Warro c26c57f457 Changed pg_restore commands to use docker instead and edited ping_psql so that it also drops existing databases before creating new ones 2019-07-03 15:56:10 +03:00
Rochet2andGitHub 3755149eec Merge pull request #1067 from UniversityOfHelsinkiCS/Rochet2-patch-1
Enable production deployment
2019-07-03 13:43:36 +03:00
Rochet2andGitHub 9dfb3a5738 Update .travis.yml 2019-07-03 13:33:44 +03:00
Rochet2andGitHub 0a69d8385b Enable production deployment 2019-07-03 13:25:20 +03:00
Rochet2andGitHub 16b42c8898 Merge pull request #1066 from UniversityOfHelsinkiCS/trunk
DB split, Fix rounding
2019-07-02 20:45:00 +03:00
Rochet2 aa1e85338b Start db_kone for DB setup in travis 2019-07-02 18:14:19 +03:00
Rochet2 534e604884 Add wait for new DB 2019-07-02 17:33:44 +03:00
Rochet2 5233f0008f Fix travis docker configs 2019-07-02 17:29:18 +03:00
Rochet2 189bd2a9cf Merge branch 'trunk' of github.com:UniversityOfHelsinkiCS/oodikone into trunk 2019-07-02 16:49:00 +03:00
Rochet2 d6bff537ed Fix tests messing up DB 2019-07-02 16:48:11 +03:00
Warro f77c89323a Fixed percentage rounding bug 2019-07-02 16:33:14 +03:00
Rochet2 e70941230c Fix tests after DB split 2019-07-02 16:30:17 +03:00
Rochet2 56c9375b33 Temporarily disable production deployment so we dont accidentally deploy DB split and destroy our data before we are ready 2019-07-02 16:27:09 +03:00
Rochet2 c803d169cb Merge branch 'trunk' of github.com:UniversityOfHelsinkiCS/oodikone into trunk 2019-07-02 15:59:23 +03:00
Rochet2 4be7937d46 Split kone_data to separate database entirely 2019-07-02 15:59:16 +03:00
esakempandGitHub 3981043c85 Merge pull request #1065 from UniversityOfHelsinkiCS/trunk
Trunk
2019-07-02 13:53:36 +03:00
Warro 92550897a2 fixed lint errors 2019-07-02 13:25:55 +03:00
Warro 64c65d215c Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-02 13:17:34 +03:00
Warro 88cb253f68 Added possibility to filter course statistics by year 2019-07-02 13:17:20 +03:00
esakemp dab4c0fb2d small front ui change 2019-07-02 12:18:38 +03:00
esakemp dc5c7b96c9 fix error message related to tags 2019-07-02 10:43:29 +03:00
esakemp 75a71bc38e Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-02 10:20:56 +03:00
esakemp 125b4cb77d minthify tag search a tiny bit 2019-07-02 10:20:49 +03:00
esakempandGitHub 673cffa5a6 Merge pull request #1064 from UniversityOfHelsinkiCS/trunk
fast fixes
2019-07-02 10:19:36 +03:00
Tuomo Torppa 276e426d34 bring back countries to frontend 2019-07-02 09:59:54 +03:00
esakemp 9a191e911d fix semesters 2019-07-02 09:46:48 +03:00
Warro cbec34c98e Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-02 08:59:47 +03:00
Warro f774fe2382 Fixed docker hot reload for mac 2019-07-01 16:20:32 +03:00
Rochet2 ad066bf549 Merge branch 'trunk' of github.com:UniversityOfHelsinkiCS/oodikone into trunk 2019-07-01 15:22:01 +03:00
Tuomo TorppaandGitHub 0ad2966e47 Merge pull request #1062 from UniversityOfHelsinkiCS/trunk
trying to hit daily quota
2019-07-01 15:06:55 +03:00
Tuomo Torppa 00be52f2e0 Merge branch 'trunk' of github.com:UniversityOfHelsinkiCS/oodikone into trunk 2019-07-01 14:48:57 +03:00
Rochet2 1c10940d1a Merge branch 'trunk' of github.com:UniversityOfHelsinkiCS/oodikone into trunk 2019-07-01 14:43:55 +03:00
Tuomo Torppa f8d71e701f home_country to population overview query 2019-07-01 14:42:50 +03:00
esakemp bec964a85f have some more minttu 2019-07-01 14:41:13 +03:00
esakemp dcc8ecb2ba Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-01 14:29:46 +03:00
esakemp c48b77c12f tag query card, other minttu sheit 2019-07-01 14:29:31 +03:00
Tuomo TorppaandGitHub f2a16455a4 Merge pull request #1061 from UniversityOfHelsinkiCS/trunk
Student home_country to db, CLI works and other lies
2019-07-01 14:03:00 +03:00
Tuomo Torppa 309844766e Merge branch 'trunk' of github.com:UniversityOfHelsinkiCS/oodikone into trunk 2019-07-01 13:38:20 +03:00
Tuomo Torppa edf0fb69a4 home country to student update 2019-07-01 13:35:39 +03:00
esakemp 58904d7d03 Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-07-01 13:34:29 +03:00
esakemp dfdd74ff14 change variable name 2019-07-01 13:34:22 +03:00
Tuomo Torppa f51451f570 Merge branch 'trunk' of github.com:UniversityOfHelsinkiCS/oodikone into trunk 2019-07-01 10:08:57 +03:00
Tuomo Torppa 255b88b687 added home_country_lang to student 2019-07-01 10:08:49 +03:00
esakemp bc0e7afacf remove clog 2019-07-01 10:02:24 +03:00
esakemp 7ffd7dfc56 year selection for tag search 2019-07-01 09:49:48 +03:00
Tuomo Torppa da0d131d52 add home_country to student tabel 2019-07-01 09:10:55 +03:00
Mäkinen Sasu S d631c69819 faculties route created 2019-06-28 17:49:23 +03:00
esakemp e6ff262dde CLI toimii 2019-06-28 15:34:49 +03:00
esakempandGitHub fa7a370862 Merge pull request #1057 from UniversityOfHelsinkiCS/trunk
custom populations are here
2019-06-28 10:31:02 +03:00
esakemp 4b9a95f3d2 search tagged population 2019-06-28 09:24:42 +03:00
Rochet2 fa74b7e2ba Fix calculation of yearly productivity 2019-06-27 16:15:34 +03:00
esakempandGitHub 34a3449249 Merge pull request #1056 from UniversityOfHelsinkiCS/trunk
Fix crash and css and js caching
2019-06-27 13:27:30 +03:00
Rochet2 6cc832d40c Merge branch 'trunk' of github.com:UniversityOfHelsinkiCS/oodikone into trunk 2019-06-27 12:51:08 +03:00
Rochet2 4bed9228d9 Fix invalidating css and js file caches 2019-06-27 12:50:59 +03:00
Mäkinen Sasu S 45b045865c rm clog 2019-06-27 10:53:17 +03:00
Mäkinen Sasu S 1da9d4b36d clicking 'label' in mandatory courses no longer crashes 2019-06-27 10:48:47 +03:00
Rochet2andGitHub aa0a5f23ef Merge pull request #1053 from UniversityOfHelsinkiCS/trunk
fixes and betterments
2019-06-26 17:36:41 +03:00
Rochet2 15517a7ff3 Merge branch 'trunk' of github.com:UniversityOfHelsinkiCS/oodikone into trunk 2019-06-26 16:53:25 +03:00
Rochet2 4ef18d6946 Populate faculty programmes 2019-06-26 16:53:09 +03:00
esakemp 1ebd0aece5 Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-06-26 15:20:45 +03:00
esakemp d801699bd1 fix tag dropdown 2019-06-26 15:20:31 +03:00
Mäkinen Sasu S 530c654dc1 fix 2 bugs with relative toggle 2019-06-26 15:13:26 +03:00
Mäkinen Sasu S 96b163dc43 delete 'all' from relative course graph 2019-06-26 14:50:02 +03:00
esakemp b086707afa Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-06-26 14:38:36 +03:00
esakemp ec5797c13f Merge branch 'trunk' of https://github.com/UniversityOfHelsinkiCS/oodikone into trunk 2019-06-26 14:03:26 +03:00
Mäkinen Sasu S 96c23fe337 fix collapse headers to deal with 'orderNumber' rather than 'key' 2019-06-26 14:00:43 +03:00
esakemp 047680f168 tag filter betterment 2019-06-26 13:57:19 +03:00
391 changed files with 26952 additions and 21278 deletions
+93
View File
@@ -0,0 +1,93 @@
version: 2.1
executors:
my-executor:
working_directory: ~/app
machine:
image: ubuntu-1604:201903-01
aliases:
- &check_exit_statuses
run:
name: check_exit_statuses
command: |
docker ps -a
if [[ $(docker ps --all | grep -Eo '(Exited|Restarting) \([0-9]+\)' | grep -Eo '[0-9]+' | awk 'BEGIN {sum=0} { sum += $1 } END { print sum }') != '0' ]]; then
echo 'Some process had nonzero exit code';
npm run docker:ci -- logs
exit 1;
fi
jobs:
build:
executor: my-executor
steps:
- run:
name: set_env_variables
command: |
echo $CIRCLE_BRANCH;
echo $CIRCLE_TAG;
if [[ -n "$CIRCLE_TAG" ]]; then
echo 'export TAG=latest' >> $BASH_ENV;
echo 'export DEPLOY=true' >> $BASH_ENV;
echo 'export CACHE_TAG=staging' >> $BASH_ENV;
echo 'USING RELEASE CONFIG';
elif [[ "$CIRCLE_BRANCH" = "master" && -z "$CIRCLE_PULL_REQUEST" ]]; then
echo 'export TAG=staging' >> $BASH_ENV;
echo 'export DEPLOY=true' >> $BASH_ENV;
echo 'export CACHE_TAG=trunk' >> $BASH_ENV;
echo 'USING STAGING CONFIG';
else
echo 'export TAG=trunk' >> $BASH_ENV;
echo 'export DEPLOY=true' >> $BASH_ENV;
echo 'export CACHE_TAG=trunk' >> $BASH_ENV;
echo 'USING TRUNK CONFIG';
fi
- checkout
- restore_cache:
keys:
- npmcache-v2-{{ checksum "package-lock.json" }}
- run: npm ci
- run: npm run cypress -- verify
- save_cache:
key: npmcache-v2-{{ checksum "package-lock.json" }}
paths:
- ~/.cache
- run: TAG=${CACHE_TAG} npm run docker:ci -- pull --ignore-pull-failures
- run: npm run docker:ci -- build
- run: npm run docker:ci -- up -d db user_db db_kone
- *check_exit_statuses
- run: git clone --depth 1 git@github.com:UniversityOfHelsinkiCS/anonyymioodi.git
- run: source ./scripts/scripts.sh && init_dirs && db_anon_setup_full
- *check_exit_statuses
- run: npm run docker:ci -- up -d --no-recreate
- run:
name: log_in_background
background: true
command: |
docker ps -a && npm run docker:ci -- logs -f
- *check_exit_statuses
- run: npm run test_services
- *check_exit_statuses
- run: timeout 5m bash -c 'until $(curl --output /dev/null --silent --fail http://localhost:1337/); do printf .; sleep 5; done'
- run: npm run cypress:ci
- *check_exit_statuses
- store_artifacts:
path: cypress/videos
- store_artifacts:
path: cypress/screenshots
- deploy:
command: |
if [ "${DEPLOY}" == "true" ]; then
docker login -u $DOCKER_USER -p $DOCKER_PASS
npm run docker:ci -- push
fi
workflows:
version: 2
build:
jobs:
- build:
filters:
tags:
only: /.*/
+3 -5
View File
@@ -1,5 +1,6 @@
data
pgdata
pgdata_kone
user_pgdata
analytics_pgdata
usage_pgdata
@@ -13,17 +14,14 @@ anonyymioodi
nginx
kafka
node_modules
cypress/support
cypress/videos
services/updater_writer/updater/test_assets/testi.bak
services/updater_writer/updater/test_assets/011120775.json
services/updater_writer/updater/test_assets/014272112.json
services/updater_writer/updater/test_assets/014441008.json
services/updater_writer/updater/test_assets/meta.json
services/updater_scheduler/all_student_numbers.txt
services/updater_scheduler/debug.log
services/updater_scheduler/active_student_numbers.txt
services/oodikone2-backend/debug.log
datastore
services/updater_api/debug.log
services/backend/updater_writer/dumps
services/backend/updater_writer/dumps
debug.log
-67
View File
@@ -1,67 +0,0 @@
language: node_js
node_js:
# Node 10.3+ includes npm@6 which has good "npm ci" command
- 10.8
cache:
# cache both npm modules and Cypress binary
npm: true
directories:
- ~/.cache
services:
- docker
before_script:
- docker --version
- docker-compose --version
- export AUTHOR_NAME="$(git log -1 ${TRAVIS_COMMIT} --pretty="%aN")"
jobs:
include:
- stage: build & test & push & deploy
if: NOT tag IS present
env:
- IMAGE=STAGING
script:
- docker login -u $DOCKER_USER -p $DOCKER_PASS
- source scripts.sh && time run_e2e_setup docker-compose.lateste2e.yml
- docker ps
- cat nginx/log
- docker-compose logs -f &
- until $(curl --output /dev/null --silent --fail http://localhost:1337/); do printf '.'; sleep 5; done
- time npm run test_services
- time CYPRESS_baseUrl=http://localhost:1337/ npm run cypress:record
- docker ps -a
- if [[ $(docker ps --all | grep -Eo '(Exited|Restarting) \([0-9]+\)' | grep -Eo '[0-9]+' | awk '{ sum += $1 } END { print sum }') != '0' ]]; then echo 'Some process had nonzero exit code'; exit 1; fi
deploy: # deploy is always skipped for PR
provider: script
skip_cleanup: true
script: "docker-compose -f docker-compose.lateste2e.yml push && curl -X POST -H 'Content-type: application/json' --data \"{\\\"text\\\":\\\"Staging auto deployment started!\\\"}\" ${SLACKBOT_URL}"
on:
branch: master
- # in parallel
if: type = pull_request OR NOT branch = master
env:
- IMAGE=PRODUCTION
script:
- docker login -u $DOCKER_USER -p $DOCKER_PASS
- source scripts.sh && time run_e2e_setup docker-compose.lateste2e.production.yml
- docker ps
- cat nginx/log
- docker-compose logs -f &
- until $(curl --output /dev/null --silent --fail http://localhost:1337/); do printf '.'; sleep 5; done
- time npm run test_services
- time CYPRESS_baseUrl=http://localhost:1337/ npm run cypress:record
- docker ps -a
- if [[ $(docker ps --all | grep -Eo '(Exited|Restarting) \([0-9]+\)' | grep -Eo '[0-9]+' | awk '{ sum += $1 } END { print sum }') != '0' ]]; then echo 'Some process had nonzero exit code'; exit 1; fi
deploy: # deploy is always skipped for PR
provider: script
skip_cleanup: true
script: "docker-compose -f docker-compose.lateste2e.production.yml push && curl -X POST -H 'Content-type: application/json' --data \"{\\\"text\\\":\\\"${TRAVIS_TAG} release started auto deployment!\\\"}\" ${SLACKBOT_URL}"
on:
tags: true
after_failure:
- "curl -X POST -H 'Content-type: application/json' --data \"{\\\"text\\\":\\\"${IMAGE} buildi paskana. STOP AND FIX tai tulee kenkää! *${AUTHOR_NAME}* ${TRAVIS_BUILD_WEB_URL}\\\"}\" ${SLACKBOT_URL}"
+8 -8
View File
@@ -23,7 +23,7 @@ Launch the CLI with the command below and follow the instructions.
Before running cli [make yourself a deployment key](https://developer.github.com/v3/guides/managing-deploy-keys/#setup-2) for Anonyymioodi private repository and put it in your root folder as private.key. This allows you to download the anonymized dumps from the repository.
```
bash run.sh
bash ./scripts/run.sh
```
For local development with anonymized data use `2) Anon setup` (you can run e2e tests with this).
@@ -58,27 +58,27 @@ The mapping of ports and environment variables are also defined in the docker-co
#### With anonymized data:
```
docker-compose up -d
npm run docker:up
```
#### With real data:
```
docker-compose -f docker-compose.yml -f docker-compose.real.yml up -d
docker-compose -f docker-compose.yml -f ./docker/docker-compose.dev.yml -f ./docker/docker-compose.dev.real.yml up -d
```
### Stop the development environment
```
docker-compose down
npm run docker:down
```
### Restart container(s)
```
docker-compose restart # all
npm run docker:restart # all
docker-compose restart backend # just backend
npm run docker:restart:backend # just backend
```
### View the containers in the running environment
@@ -90,9 +90,9 @@ docker-compose ps
```
docker-compose logs -f # all
npm run docker:logs # all
docker-compose logs -f backend # just backend
npm run docker:logs:backend # just backend
```
+1 -1
View File
@@ -6,6 +6,6 @@ require_once('plugins/login-servers.php');
* @param string
*/
return new AdminerLoginServers(
$servers = array("db" => "db", "user_db" => "user_db", "analytics_db" => "analytics_db"),
$servers = array("db" => "db", "db_kone" => "db_kone", "user_db" => "user_db", "analytics_db" => "analytics_db"),
$driver = "pgsql"
);
+1
View File
@@ -1 +1,2 @@
screenshots
videos
+2 -2
View File
@@ -51,8 +51,8 @@ describe('Course Statistics tests', () => {
cy.url().should('include', '/coursestatistics')
cy.contains("Search for courses")
cy.get("input[placeholder='Search by entering a course code']").type('TKT')
cy.contains("tr", "TKT20003").click()
cy.contains("tr", "TKT10002").click()
cy.contains("td", "TKT20003").click()
cy.contains("td", /^TKT10002/).click()
cy.contains("Fetch statistics").should('be.enabled').click()
cy.contains("Search for courses").should('not.exist')
+45 -23
View File
@@ -78,6 +78,21 @@ describe('Population Statistics tests', () => {
cy.contains("Excludes students with cancelled study right")
})
cy.contains("Courses of Population").parentsUntil(".ui.segment").parent().within(() => {
cy.get("tr").its('length').should('be.gte', 10)
cy.route('/api/v3/courseyearlystats**').as('coursePage')
cy.contains("Opiskelijan digitaidot: orientaatio").siblings().find(".level").click()
cy.wait('@coursePage')
cy.url().should('include', '/coursestatistics')
})
cy.contains("DIGI-000A")
cy.go("back")
cy.contains("Courses of Population").parentsUntil(".ui.segment").parent().within(() => {
cy.contains("number at least").siblings().within(() => cy.get("input").clear().type("0"))
cy.contains("Matematiikan didaktiikka").siblings().eq(2).should("have.text", '9')
})
cy.contains("add").click()
cy.contains("Add filters").siblings().within(() => {
cy.get(".form").should('have.length', 10)
@@ -88,39 +103,48 @@ describe('Population Statistics tests', () => {
let filteredStudents = 1328493
cy.contains("Credits gained during first").parentsUntil(".tab").get("table").within(() => {
cy.get("tr").eq(1).find("td").eq(1).invoke("text").then(text => filteredStudents = Number(text))
cy.route('POST', '/api/v2/populationstatistics/courses**').as('courseData')
cy.get("tr").eq(1).click()
cy.wait('@courseData')
}).then(() => {
checkAmountOfStudents(filteredStudents)
})
cy.contains("Courses of Population").parentsUntil(".ui.segment").parent().within(() => {
cy.get("tr").its('length').should('be.gte', 10)
cy.contains("Opiskelijan digitaidot: orientaatio").siblings().find(".level").click()
cy.wait(1000)
cy.url().should('include', '/coursestatistics')
})
cy.contains("DIGI-000A")
cy.go("back")
cy.contains("Courses of Population").parentsUntil(".ui.segment").parent().within(() => {
cy.contains("number at least").siblings().within(() => cy.get("input").clear().type("0"))
cy.contains("Matematiikan didaktiikka").siblings().eq(2).should("have.text", '9')
})
cy.contains("Courses of Population").parentsUntil(".ui.segment").parent().within(() => {
cy.get(".refresh").click()
cy.contains("number at least").siblings().within(() => cy.get("input").clear().type("0"))
cy.contains("number at least").siblings().within(() => cy.get("input").clear())
cy.contains("number at least").siblings().within(() => cy.get("input").type("0"))
cy.contains("Matematiikan didaktiikka").siblings().eq(2).should("have.text", '1')
})
cy.get("button").contains("show").click()
cy.contains("button", "show").click()
cy.contains("Student names hidden").click()
cy.contains("Oinonen").siblings().eq(2).click()
cy.contains("Oinonen").invoke('text').then((text) => expect(text).to.equal('Oinonen Heidi Eeva Elisabet, 014473717'))
})
it('Student list checking works as intended', () => {
cy.contains("Select study programme").click().siblings().contains("Kasvatustieteiden kandiohjelma").click()
cy.contains("See population").click()
cy.contains("button", "show").click()
cy.contains("010483918")
cy.contains("666666666").should('not.exist')
cy.contains('button', "Check studentnumbers").click()
cy.contains('Check for studentnumbers')
cy.get('textarea').type("010483918").type('{enter}').type("666666666")
cy.contains('button', 'check students').click()
cy.contains('form', 'Results').within(e => {
cy.get('div').eq(0).within(e => {
cy.contains('student numbers in list but not in oodi')
cy.contains('666666666')
})
cy.get('div').eq(2).within(e => {
cy.contains('student numbers in oodi but not in list')
cy.contains('014896381')
})
cy.contains('010483918').should('not.exist')
})
})
it('All filters working', () => {
cy.contains("Select study programme", { timeout: 50000 }).click().siblings().contains("Kasvatustieteiden kandiohjelma").click()
cy.contains("See population").click()
@@ -185,8 +209,7 @@ describe('Population Statistics tests', () => {
cy.contains("and at least").parentsUntil("form").contains("set filter").click()
cy.contains("Filters").siblings().within(() => {
cy.contains('Kehittävä').should('have.text', 'Kehittävä työntutkimus')
cy.contains('Kvalitatiiviset').should('have.text', 'Kvalitatiiviset tutkimusmenetelmät I')
cy.contains('Kehittävä').should('have.text', 'Avoin yo: Kehittävä työntutkimus')
})
checkAmountOfStudents(1)
@@ -205,7 +228,6 @@ describe('Population Statistics tests', () => {
cy.contains('Excluded students that graduated')
cy.contains("Students that has").parentsUntil("form").within(() => {
cy.contains("degree").click().siblings().contains("any degree").click()
cy.contains("programme").click().siblings().contains("Kasvatustieteiden kandiohjelma")
@@ -213,7 +235,7 @@ describe('Population Statistics tests', () => {
cy.contains("set filter").click()
})
checkAmountOfStudents(1)
checkAmountOfStudents(3)
cy.contains("Basic filters").parentsUntil("form").contains("set filter").click()
+9 -2
View File
@@ -11,7 +11,6 @@ describe('Student Statistics tests', () => {
}
}
})
console.log(Cypress.config().baseUrl)
cy.visit(Cypress.config().baseUrl)
cy.contains("Student statistics").click()
cy.contains("Student names hidden")
@@ -71,4 +70,12 @@ describe('Student Statistics tests', () => {
cy.get('.prompt').clear().type('01114')
cy.contains('Student number').should('not.exist')
})
})
it('Can jump to population page', () => {
cy.get('.prompt').type('Oinonen')
cy.contains('011143561').click()
cy.get('i.level.up.alternate.icon').eq(0).click()
cy.contains('Population statistics')
cy.contains('Credit accumulation (for 1 students)')
})
})
+54 -10
View File
@@ -41,22 +41,66 @@ describe('Studyprogramme overview', () => {
it('renders progress and productivity tables', () => {
cy.contains("Tietojenkäsittelytieteen kandiohjelma").click()
cy.get('table').should('have.length', 2)
cy.contains('Population progress')
cy.contains('Yearly productivity')
cy.contains("2018-2019").siblings().contains('9')
cy.contains("2017-2018").siblings().contains('12').siblings().contains('7').siblings().contains('2')
cy.get('table').eq(1).contains('2018').siblings().contains('443')
cy.get('table').eq(1).contains('2017').siblings().contains('381')
cy.get('button:contains("Recalculate")').eq(0).click()
cy.get('button:contains("Recalculate")').eq(1).click()
cy.contains('Loading...').should('not.be.visible').then(() => {
cy.wait(1000)
cy.reload()
cy.get('table').should('have.length', 2)
cy.contains('Population progress')
cy.contains('Yearly productivity')
cy.contains("2018-2019").siblings().contains('9')
cy.contains("2017-2018").siblings().contains('12').siblings().contains('7').siblings().contains('2')
cy.get('table').eq(1).contains('2018').siblings().contains('443')
cy.get('table').eq(1).contains('2017').siblings().contains('381')
})
})
it('can search for mandatory courses', () => {
it('can add and delete mandatory courses and labels', () => {
cy.contains("Tietojenkäsittelytieteen kandiohjelma").click()
cy.contains('Mandatory Courses').click()
cy.get('button').contains('Add Courses').click()
cy.get('input').eq(0).type('CSM')
cy.route('/api/v2/coursesmulti**').as('searchResponse')
cy.get('input').eq(1).type('Code Generation')
cy.wait('@searchResponse')
cy.contains('Searched courses')
cy.contains('Code Generation')
cy.get('table').eq(0).contains('Code Generation').click()
cy.get('table').eq(1).contains('tr', 'Code Generation').contains('select label')
cy.contains('Group labels').click()
const label = 'cypress test label'
cy.contains(label).should('not.exist')
cy.contains('button', 'Add').should('be.disabled')
cy.get('input').eq(0).type(label)
cy.contains('button', 'Add').should('be.enabled').click()
cy.contains('button', 'Add').should('be.disabled')
cy.contains('table', label)
cy.contains('Mandatory courses').click()
cy.get('table').eq(0).contains('tr', 'Code Generation').contains('select label').click()
cy.contains(label).click()
cy.get('table').eq(0).contains('tr', 'Code Generation').within((el) => {
cy.get('div.dropdown>div').eq(0).within((el) => {
cy.contains('select label').should('not.exist')
cy.contains(label)
})
cy.get('i.clear').click()
cy.get('div.dropdown>div').eq(0).within((el) => {
cy.contains(label).should('not.exist')
cy.contains('select label')
})
})
cy.get('table').eq(0).contains('tr', 'Code Generation').contains('select label').click()
cy.contains(label).click()
cy.get('table').eq(0).contains('tr', 'Code Generation').contains('button', 'Delete').click()
cy.contains('Code Generation').should('not.exist')
cy.contains('Group labels').click()
cy.contains('tr', label).within((el) => {
cy.get('i.remove').click()
})
cy.contains('button', 'Remove').click()
cy.contains(label).should('not.exist')
})
it('can open Thesis page', () => {
+71
View File
@@ -0,0 +1,71 @@
describe('Teachers page tests', () => {
beforeEach(() => {
cy.server({
onAnyRequest: function (route, proxy) {
if (Cypress.config().baseUrl.includes("http://localhost:1337/")) {
proxy.xhr.setRequestHeader('uid', 'tktl')
proxy.xhr.setRequestHeader('shib-session-id', 'mock-shibboleth')
proxy.xhr.setRequestHeader('hygroupcn', 'grp-oodikone-users')
proxy.xhr.setRequestHeader('edupersonaffiliation', 'asdasd')
}
}
})
cy.visit(Cypress.config().baseUrl)
cy.reload()
cy.contains("Teachers").click()
cy.contains("Teacher statistics by course providers")
})
it("Check Statistics", () => {
cy.get(':nth-child(1) > .ui > .search').click()
cy.contains('Autumn 2017').click()
cy.get('.form > :nth-child(2) > .ui').click()
cy.contains('Tietojenkäsittelytieteen kandiohjelma').click()
cy.get('.form > .fluid').click()
cy.contains('Name')
cy.contains('Wu')
cy.contains('Jämsä')
cy.contains('Kuusinen')
})
it("Teacher search works", () => {
cy.url().should('include', '/teachers')
cy.get('.borderless > :nth-child(3)').click()
cy.get('.prompt').type('Pekka')
cy.contains('Professori Pekka')
cy.contains('Saren')
cy.contains('Jari')
cy.contains('Lopez')
})
it("Can check teacher page", () => {
cy.url().should('include', '/teachers')
cy.get('.borderless > :nth-child(3)').click()
cy.get('.prompt').type('Pekka')
cy.contains('Saren').click()
cy.contains('English Academic & Professional Skills: Reading, Writing & Spoken Communication (CEFR B2)*')
})
it("Can check teacher page if teacher doesn't have courses", () => {
cy.url().should('include', '/teachers')
cy.get('.borderless > :nth-child(3)').click()
cy.get('.prompt').type('Pekka')
cy.contains('Professori').click()
cy.contains('Name').should('not.exist')
})
it("Check leaderboad works", () => {
cy.get('.borderless > :nth-child(2)').click()
cy.get(':nth-child(1) > .ui > .search').click()
cy.contains('2017-18').click()
cy.contains("Recalculate this year").click()
cy.wait(5000)
cy.reload()
cy.get(':nth-child(1) > .ui > .search').click()
cy.contains('2017-18').click()
cy.contains("Passed")
cy.contains("Valtonen")
cy.contains("Wahlström")
})
})
+4 -1
View File
@@ -15,7 +15,7 @@ describe('Users tests', () => {
cy.visit(Cypress.config().baseUrl)
cy.reload()
cy.contains("Users").click()
cy.contains("Enable or disable access to Oodikone")
cy.contains("Oodikone users")
})
it("Admin mocking normal user shows only the mocked user's programmes", () => {
@@ -27,8 +27,11 @@ describe('Users tests', () => {
cy.get("div[role='listitem']").should('have.length', 1).contains("Tietojenkäsittelytieteen kandiohjelma")
})
cy.route('POST', '/api/superlogin/normk').as('superlogin')
cy.get('i.spy').click()
cy.wait('@superlogin')
cy.contains("mocking as normk")
cy.wait(1000)
cy.contains("Study programme").click().siblings().contains("Search by class").click()
cy.contains("label", "Study programme")
cy.contains("label", "Study programme").siblings().within(($row) => {
+25
View File
@@ -0,0 +1,25 @@
// ***********************************************
// This example commands.js shows you how to
// create various custom commands and overwrite
// existing commands.
//
// For more comprehensive examples of custom
// commands please read more here:
// https://on.cypress.io/custom-commands
// ***********************************************
//
//
// -- This is a parent command --
// Cypress.Commands.add("login", (email, password) => { ... })
//
//
// -- This is a child command --
// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... })
//
//
// -- This is a dual command --
// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... })
//
//
// -- This is will overwrite an existing command --
// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
+31
View File
@@ -0,0 +1,31 @@
// ***********************************************************
// This example support/index.js is processed and
// loaded automatically before your test files.
//
// This is a great place to put global configuration and
// behavior that modifies Cypress.
//
// You can change the location of this file or turn off
// automatically serving support files with the
// 'supportFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/configuration
// ***********************************************************
// Import commands.js using ES2015 syntax:
import './commands'
// Alternatively you can use CommonJS syntax:
// require('./commands')
// describe('Before all tests', () => {
// it('reset anon database', () => {
// cy.exec(
// 'source ./scripts/scripts.sh && time reset_db_for_cypress',
// { timeout: 5*60*1000 }
// ).then(result => {
// console.log(result)
// })
// })
// })
-236
View File
@@ -1,236 +0,0 @@
version: '3'
services:
nats:
image: nats-streaming
command: -cid updaterNATS
expose:
- "4222"
container_name: nats
analytics_db:
image: postgres:9.6.3
ports:
- "5423:5432"
volumes:
- ./analytics_pgdata:/var/lib/postgresql/data
container_name: oodi_analytics_db
environment:
- POSTGRES_USER=postgres
- POSTGRES_DB=analytics_db
user_db:
image: postgres:9.6.3
ports:
- "5422:5432"
volumes:
- ./user_pgdata:/var/lib/postgresql/data
container_name: oodi_user_db
environment:
- POSTGRES_USER=postgres
- POSTGRES_DB=user_db
db:
image: postgres:9.6.3
ports:
- "5421:5432"
volumes:
- ./pgdata:/var/lib/postgresql/data
- ./scripts/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d:ro
container_name: oodi_db
environment:
- POSTGRES_MULTIPLE_DATABASES=tkt_oodi,tkt_oodi_test
- POSTGRES_USER=postgres
redis:
image: redis
command: ["redis-server", "--appendonly", "yes"]
ports:
- "6379:6379"
volumes:
- ./redis-data:/data
container_name: redis
analytics_redis:
image: redis
command: ["redis-server", "--appendonly", "yes"]
ports:
- "6380:6379"
volumes:
- ./analytics-redis-data:/data
container_name: analytics_redis
backend:
image: toska/oodikone2-backend:latest
build:
context: services/backend
dockerfile: oodikone2-backend/Dockerfile
ports:
- "8080:8080"
- "9229:9229"
environment:
WAIT_HOSTS: redis:6379,db:5432,nats:4222
REDIS: redis
DB_URL: postgres://postgres@db:5432/tkt_oodi
TEST_DB: postgres://postgres@db:5432/tkt_oodi_test
FRONT_URL: http://localhost:1337
TOKEN_SECRET: IWannaBeTheVeryBest
OODILEARN_URL: http://oodilearn:5000
USERSERVICE_URL: http://userservice:4567
USAGESERVICE_URL: http://usageservice:545
USERSERVICE_SECRET: Luukk4inenApprov3dVitunMinttuSalainenAvain666NurmivaaraPJ2019
USAGESERVICE_SECRET: Luukk4inenApprov3dVitunMinttuSalainenAvain666NurmivaaraPJ2019
ANALYTICS_ADMINER_URL: http://localhost:5050/?pgsql=analytics_db&username=postgres
ANALYTICS_URL: http://analytics:4568
NATS_URI: nats://nats:4222
DB_SCHEMA_KONE: kone_data
container_name: backend
depends_on:
- db
- redis
- nats
frontend:
image: toska/oodikone2-frontend:latest
build:
context: services/oodikone2-frontend
args:
BASE_PATH: /
ports:
- "5000:5000"
environment:
WAIT_HOSTS: user_db:5432
BACKEND_ADDR: backend
ADMINER_URL: http://localhost:5050/?pgsql=db&username=postgres
container_name: frontend
userservice:
image: toska/oodikone2-userservice:latest
build:
context: services/oodikone2-userservice
ports:
- 4567:4567
environment:
- WAIT_HOSTS=user_db:5432
- DB_URL=postgres://postgres@user_db:5432/user_db
- TEST_DB=postgres://postgres@user_db:5432/user_db_test
- SECRET=Luukk4inenApprov3dVitunMinttuSalainenAvain666NurmivaaraPJ2019
- TOKEN_SECRET=IWannaBeTheVeryBest
depends_on:
- user_db
container_name: userservice
usageservice:
image: toska/oodikone2-usageservice:latest
build:
context: services/oodikone2-usageservice
ports:
- 545:545
environment:
- WAIT_HOSTS=usage_db:5432
- PORT=545
- DB_URL=postgres://postgres@usage_db:5432/usage_db
- SECRET=Luukk4inenApprov3dVitunMinttuSalainenAvain666NurmivaaraPJ2019
depends_on:
- usage_db
container_name: usageservice
usage_db:
image: postgres:9.6.3
ports:
- "5424:5432"
volumes:
- ./usage_pgdata:/var/lib/postgresql/data
container_name: oodi_usage_db
environment:
- POSTGRES_USER=postgres
- POSTGRES_DB=usage_db
analytics:
image: toska/oodikone2-analytics:latest
build:
context: services/oodikone2-analytics
ports:
- 4568:4568
environment:
- WAIT_HOSTS=analytics_db:5432,analytics_redis:6379
- REDIS=analytics_redis
- DB_URL=postgres://postgres@analytics_db:5432/analytics_db
- TEST_DB=postgres://postgres@analytics_db:5432/analytics_db_test
depends_on:
- analytics_db
- analytics_redis
container_name: analytics
updater_api:
image: toska/updater_api:latest
build:
context: services/updater_api
depends_on:
- nats
environment:
- WAIT_HOSTS=nats:4222
- NATS_URI=nats://nats:4222
- OODI_ADDR=https://oodikone.cs.helsinki.fi/oodi
- TOKEN=toskab1gs8cret5
container_name: updater_api
updater_writer:
image: toska/updater_writer:latest
build:
context: services/backend
dockerfile: updater_writer/Dockerfile
depends_on:
- nats
- db
environment:
WAIT_HOSTS: nats:4222,db:5432
NATS_URI: nats://nats:4222
DB_URL: postgres://postgres@db:5432/tkt_oodi
TEST_DB: postgres://postgres@db:5432/tkt_oodi_test
TEST_DB_SCHEMA: updater_test
container_name: updater_writer
scheduler_mongo:
image: mongo
volumes:
- ./mongodata:/data/db
expose:
- "27017"
container_name: scheduler_db
updater_scheduler:
image: toska/updater_scheduler:latest
build:
context: services/updater_scheduler
command: ["echo", "mluukkai on orjuuttaja"]
depends_on:
- nats
- scheduler_mongo
environment:
- WAIT_HOSTS=nats:4222,scheduler_mongo:27017
- NATS_URI=nats://nats:4222
- MONGO_URI=mongodb://scheduler_mongo:27017
- STUDENT_NUMBERS=./all_student_numbers.txt
- ACTIVE_STUDENTS=./active_student_numbers.txt
- OODI_ADDR=https://oodikone.cs.helsinki.fi/oodi
- TOKEN=toskab1gs8cret5
container_name: updater_scheduler
nginx:
image: nginx:latest
volumes:
- ./nginx.production.conf:/etc/nginx/nginx.conf
- ./nginx/error.log:/etc/nginx/error_log.log
- ./nginx/log:/var/log/nginx/localhost.error_log
- ./nginx/cache/:/etc/nginx/cache
- /etc/letsencrypt/:/etc/letsencrypt/
ports:
- 1337:80
depends_on:
- frontend
- backend
- userservice
- analytics
container_name: nginx
-238
View File
@@ -1,238 +0,0 @@
version: '3'
services:
nats:
image: nats-streaming
command: -cid updaterNATS --file_slice_max_bytes 0 --file_slice_max_age 100h -store file -dir datastore
expose:
- "4222"
volumes:
- ./datastore:/datastore
container_name: nats
analytics_db:
image: postgres:9.6.3
ports:
- "5423:5432"
volumes:
- ./analytics_pgdata:/var/lib/postgresql/data
container_name: oodi_analytics_db
environment:
- POSTGRES_USER=postgres
- POSTGRES_DB=analytics_db
user_db:
image: postgres:9.6.3
ports:
- "5422:5432"
volumes:
- ./user_pgdata:/var/lib/postgresql/data
container_name: oodi_user_db
environment:
- POSTGRES_USER=postgres
- POSTGRES_DB=user_db
db:
image: postgres:9.6.3
ports:
- "5421:5432"
volumes:
- ./pgdata:/var/lib/postgresql/data
- ./scripts/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d:ro
container_name: oodi_db
environment:
- POSTGRES_MULTIPLE_DATABASES=tkt_oodi,tkt_oodi_test
- POSTGRES_USER=postgres
redis:
image: redis
command: ["redis-server", "--appendonly", "yes"]
ports:
- "6379:6379"
volumes:
- ./redis-data:/data
container_name: redis
analytics_redis:
image: redis
command: ["redis-server", "--appendonly", "yes"]
ports:
- "6380:6379"
volumes:
- ./analytics-redis-data:/data
container_name: analytics_redis
backend:
image: toska/oodikone2-backend:staging
build:
context: services/backend
dockerfile: oodikone2-backend/Dockerfile
ports:
- "8080:8080"
- "9229:9229"
environment:
WAIT_HOSTS: redis:6379,db:5432,nats:4222
REDIS: redis
DB_URL: postgres://postgres@db:5432/tkt_oodi
TEST_DB: postgres://postgres@db:5432/tkt_oodi_test
FRONT_URL: http://localhost:1337
TOKEN_SECRET: IWannaBeTheVeryBest
OODILEARN_URL: http://oodilearn:5000
USERSERVICE_URL: http://userservice:4567
USAGESERVICE_URL: http://usageservice:545
USERSERVICE_SECRET: Luukk4inenApprov3dVitunMinttuSalainenAvain666NurmivaaraPJ2019
USAGESERVICE_SECRET: Luukk4inenApprov3dVitunMinttuSalainenAvain666NurmivaaraPJ2019
ANALYTICS_ADMINER_URL: http://localhost:5050/?pgsql=analytics_db&username=postgres
ANALYTICS_URL: http://analytics:4568
NATS_URI: nats://nats:4222
DB_SCHEMA_KONE: kone_data
container_name: backend
depends_on:
- db
- redis
- nats
frontend:
image: toska/oodikone2-frontend:staging
build:
context: services/oodikone2-frontend
args:
BASE_PATH: /
ports:
- "5000:5000"
environment:
WAIT_HOSTS: user_db:5432
BACKEND_ADDR: backend
ADMINER_URL: http://localhost:5050/?pgsql=db&username=postgres
container_name: frontend
userservice:
image: toska/oodikone2-userservice:staging
build:
context: services/oodikone2-userservice
ports:
- 4567:4567
environment:
- WAIT_HOSTS=user_db:5432
- DB_URL=postgres://postgres@user_db:5432/user_db
- TEST_DB=postgres://postgres@user_db:5432/user_db_test
- SECRET=Luukk4inenApprov3dVitunMinttuSalainenAvain666NurmivaaraPJ2019
- TOKEN_SECRET=IWannaBeTheVeryBest
depends_on:
- user_db
container_name: userservice
usageservice:
image: toska/oodikone2-usageservice:staging
build:
context: services/oodikone2-usageservice
ports:
- 545:545
environment:
- WAIT_HOSTS=usage_db:5432
- PORT=545
- DB_URL=postgres://postgres@usage_db:5432/usage_db
- SECRET=Luukk4inenApprov3dVitunMinttuSalainenAvain666NurmivaaraPJ2019
depends_on:
- usage_db
container_name: usageservice
usage_db:
image: postgres:9.6.3
ports:
- "5424:5432"
volumes:
- ./usage_pgdata:/var/lib/postgresql/data
container_name: oodi_usage_db
environment:
- POSTGRES_USER=postgres
- POSTGRES_DB=usage_db
analytics:
image: toska/oodikone2-analytics:staging
build:
context: services/oodikone2-analytics
ports:
- 4568:4568
environment:
- WAIT_HOSTS=analytics_db:5432,analytics_redis:6379
- REDIS=analytics_redis
- DB_URL=postgres://postgres@analytics_db:5432/analytics_db
- TEST_DB=postgres://postgres@analytics_db:5432/analytics_db_test
depends_on:
- analytics_db
- analytics_redis
container_name: analytics
updater_api:
image: toska/updater_api:staging
build:
context: services/updater_api
depends_on:
- nats
environment:
- WAIT_HOSTS=nats:4222
- NATS_URI=nats://nats:4222
- OODI_ADDR=https://oodikone.cs.helsinki.fi/oodi
- TOKEN=toskab1gs8cret5
container_name: updater_api
updater_writer:
image: toska/updater_writer:staging
build:
context: services/backend
dockerfile: updater_writer/Dockerfile
depends_on:
- nats
- db
environment:
WAIT_HOSTS: nats:4222,db:5432
NATS_URI: nats://nats:4222
DB_URL: postgres://postgres@db:5432/tkt_oodi
TEST_DB: postgres://postgres@db:5432/tkt_oodi_test
TEST_DB_SCHEMA: updater_test
container_name: updater_writer
scheduler_mongo:
image: mongo
volumes:
- ./mongodata:/data/db
expose:
- "27017"
container_name: scheduler_db
updater_scheduler:
image: toska/updater_scheduler:staging
build:
context: services/updater_scheduler
command: ["echo", "mluukkai on orjuuttaja"]
depends_on:
- nats
- scheduler_mongo
environment:
- WAIT_HOSTS=nats:4222,scheduler_mongo:27017
- NATS_URI=nats://nats:4222
- MONGO_URI=mongodb://scheduler_mongo:27017
- STUDENT_NUMBERS=./all_student_numbers.txt
- ACTIVE_STUDENTS=./active_student_numbers.txt
- OODI_ADDR=https://oodikone.cs.helsinki.fi/oodi
- TOKEN=toskab1gs8cret5
container_name: updater_scheduler
nginx:
image: nginx:latest
volumes:
- ./nginx.staging.conf:/etc/nginx/nginx.conf
- ./nginx/error.log:/etc/nginx/error_log.log
- ./nginx/log:/var/log/nginx/localhost.error_log
- ./nginx/cache/:/etc/nginx/cache
- /etc/letsencrypt/:/etc/letsencrypt/
ports:
- 1337:80
depends_on:
- frontend
- backend
- userservice
- analytics
container_name: nginx
+29 -172
View File
@@ -1,43 +1,17 @@
version: '3'
version: '3.2'
services:
# zookeeper:
# image: wurstmeister/zookeeper
# ports:
# - "2181:2181"
# environment:
# - KAFKA_BROKER_ID=1
# container_name: zookeeper
# kafka:
# image: wurstmeister/kafka
# container_name: kafka
# depends_on:
# - zookeeper
# ports:
# - "9092:9092"
# environment:
# - HOSTNAME_COMMAND=route -n | awk '/UG[ \t]/{print $$2}'
# - KAFKA_ZOOKEEPER_CONNECT=zookeeper:2181
# - KAFKA_AUTO_CREATE_TOPICS_ENABLE=true
# - KAFKA_DELETE_TOPIC_ENABLE=true
# - KAFKA_CREATE_TOPICS=studentnumbers:1:1,priority_studentnumbers:1:1
# - KAFKA_LOG_DIRS=/kafka/kafka-logs-1
# volumes:
# - ./kafka/docker.sock:/var/run/docker.sock
# - ./kafka/logs:/kafka/kafka-logs-1
nats:
image: nats-streaming
command: -cid updaterNATS --file_slice_max_bytes 0 --file_slice_max_age 100h -store file -dir datastore
image: nats-streaming:0.15.1
command: -cid updaterNATS --file_slice_max_bytes 0 --file_slice_max_age 100h -store file -dir datastore
expose:
- "4222"
volumes:
- ./datastore:/datastore
ports:
- "8222:8222"
- "4222:4222"
container_name: nats
volumes:
- ./datastore:/datastore
analytics_db:
image: postgres:9.6.3
@@ -59,7 +33,6 @@ services:
container_name: oodi_user_db
environment:
- POSTGRES_USER=postgres
- POSTGRES_MULTIPLE_DATABASES=user_db,user_db_real
usage_db:
image: postgres:9.6.3
@@ -73,7 +46,7 @@ services:
- POSTGRES_DB=usage_db
db:
image: postgres:9.6.3
image: postgres:10-alpine
ports:
- "5421:5432"
volumes:
@@ -81,7 +54,18 @@ services:
- ./scripts/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d:ro
container_name: oodi_db
environment:
- POSTGRES_MULTIPLE_DATABASES=tkt_oodi,tkt_oodi_test,tkt_oodi_real
- POSTGRES_USER=postgres
db_kone:
image: postgres:9.6.3
ports:
- "5425:5432"
volumes:
- ./pgdata_kone:/var/lib/postgresql/data
- ./scripts/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d:ro
container_name: db_kone
environment:
- POSTGRES_MULTIPLE_DATABASES=db_kone
- POSTGRES_USER=postgres
redis:
@@ -93,32 +77,18 @@ services:
- ./redis-data:/data
container_name: redis
# mongo_db:
# image: mongo
# restart: unless-stopped
# volumes:
# - ./backups/mongo/oodilearn:/dump
# - ./mongodata:/data/db
# ports:
# - "27017:27017"
# container_name: mongo_db
backend:
build:
context: services/backend
dockerfile: oodikone2-backend/Dockerfile
args:
NODE_ENV: 'development'
command: ['sh', '-c', 'cp -r /usr/src/cache/node_modules/. /usr/src/app/node_modules/ && /wait && npm run dev']
restart: unless-stopped
ports:
- "8080:8080"
environment:
WAIT_HOSTS: redis:6379,db:5432,nats:4222
REDIS: redis
DB_URL: postgres://postgres@db:5432/tkt_oodi
DB_URL_KONE: postgres://postgres@db_kone:5432/db_kone
TEST_DB: postgres://postgres@db:5432/tkt_oodi_test
FRONT_URL: http://localhost:8000
TEST_DB_KONE: postgres://postgres@db_kone:5432/db_kone_test
TOKEN_SECRET: IWannaBeTheVeryBest
OODILEARN_URL: http://oodilearn:5000
USERSERVICE_URL: http://userservice:4567
@@ -127,13 +97,7 @@ services:
USAGESERVICE_SECRET: Luukk4inenApprov3dVitunMinttuSalainenAvain666NurmivaaraPJ2019
ANALYTICS_URL: http://analytics:4568
NATS_URI: nats://nats:4222
DB_SCHEMA_KONE: kone_data
volumes:
- ./services/backend/oodikone2-backend/:/usr/src/app
- ./services/backend/shared/models:/usr/src/app/src/models
- ./services/backend/shared/migrations:/usr/src/app/src/database/migrations
- ./services/backend/shared/migrations_kone:/usr/src/app/src/database/migrations_kone
UPDATER_URL: http://updater_scheduler:3678
container_name: backend
depends_on:
- db
@@ -143,52 +107,17 @@ services:
frontend:
build:
context: services/oodikone2-frontend
args:
NODE_ENV: 'development'
command: ['sh', '-c', 'cp -r /usr/src/cache/node_modules/. /usr/src/app/node_modules/ && /wait && npm run docker']
restart: unless-stopped
ports:
- "8081:8081"
- "7777:7777"
environment:
BACKEND_ADDR: backend
ADMINER_URL: http://localhost:5050/?pgsql=db&username=postgres
USER_ADMINER_URL: http://localhost:5050/?pgsql=user_db&username=postgres
ANALYTICS_ADMINER_URL: http://localhost:5050/?pgsql=analytics_db&username=postgres
USAGE_ADMINER_URL: http://localhost:5050/?pgsql=usage_db&username=postgres
volumes:
- ./services/oodikone2-frontend/:/usr/src/app
container_name: frontend
# oodilearn:
# build:
# context: services/oodilearn/server
# dockerfile: Dockerfile
# restart: unless-stopped
# volumes:
# - ./services/oodilearn/data:/data
# - ./services/oodilearn/server:/src
# - ./services/oodilearn/models:/models
# ports:
# - "5000:5000"
# environment:
# - ENV=development
# - MONGO_URI=mongodb://mongo_db:27017/oodilearn
# container_name: oodilearn
userservice:
build:
context: services/oodikone2-userservice
args:
NODE_ENV: 'development'
command: ['sh', '-c', 'cp -r /usr/src/cache/node_modules/. /usr/src/app/node_modules/ && /wait && npm run dev']
restart: unless-stopped
volumes:
- ./services/oodikone2-userservice/:/usr/src/app
ports:
- 4567:4567
environment:
WAIT_HOSTS: user_db:5432
DB_URL: postgres://postgres@user_db:5432/user_db
TEST_DB: postgres://postgres@user_db:5432/user_db_test
SECRET: Luukk4inenApprov3dVitunMinttuSalainenAvain666NurmivaaraPJ2019
@@ -200,19 +129,12 @@ services:
usageservice:
build:
context: services/oodikone2-usageservice
args:
NODE_ENV: 'development'
command: ['sh', '-c', 'cp -r /usr/src/cache/node_modules/. /usr/src/app/node_modules/ && /wait && npm run dev']
restart: unless-stopped
ports:
- 545:545
environment:
WAIT_HOSTS: usage_db:5432
PORT: '545'
DB_URL: postgres://postgres@usage_db:5432/usage_db
SECRET: Luukk4inenApprov3dVitunMinttuSalainenAvain666NurmivaaraPJ2019
volumes:
- ./services/oodikone2-usageservice/:/usr/src/app
depends_on:
- usage_db
container_name: usageservice
@@ -220,121 +142,56 @@ services:
updater_api:
build:
context: services/updater_api
args:
NODE_ENV: 'development'
command: ['sh', '-c', 'cp -r /usr/src/cache/node_modules/. /usr/src/app/node_modules/ && /wait && npm run dev']
restart: unless-stopped
volumes:
- ./services/updater_api/:/usr/src/app
depends_on:
- nats
environment:
- WAIT_HOSTS=nats:4222
- NATS_URI=nats://nats:4222
- OODI_ADDR=https://oodikone.cs.helsinki.fi/oodi
- TOKEN=toskab1gs8cret5
container_name: updater_api
- TOKEN=jotaindiibadaabaa
#container_name: updater_api
updater_writer:
build:
context: services/backend
dockerfile: updater_writer/Dockerfile
args:
NODE_ENV: 'development'
command: ['sh', '-c', 'cp -r /usr/src/cache/node_modules/. /usr/src/app/node_modules/ && /wait && npm run dev']
restart: unless-stopped
volumes:
- ./services/backend/updater_writer/:/usr/src/app
- ./services/backend/shared/models:/usr/src/app/models
- ./services/backend/shared/migrations:/usr/src/app/database/migrations
- ./services/backend/shared/migrations_kone:/usr/src/app/database/migrations_kone
depends_on:
- nats
- db
environment:
WAIT_HOSTS: nats:4222,db:5432
NATS_URI: nats://nats:4222
DB_URL: postgres://postgres@db:5432/tkt_oodi
TEST_DB: postgres://postgres@db:5432/tkt_oodi_test
TEST_DB_SCHEMA: updater_test
DB_SCHEMA_KONE: kone_data
#container_name: updater_writer
scheduler_mongo:
image: mongo
restart: unless-stopped
image: mongo:4.0.10
volumes:
- ./mongodata:/data/db
expose:
- "27017"
container_name: scheduler_db
container_name: scheduler_mongo
updater_scheduler:
build:
context: services/updater_scheduler
args:
NODE_ENV: 'development'
command: ['sh', '-c', 'cp -r /usr/src/cache/node_modules/. /usr/src/app/node_modules/ && /wait && npm run dev']
restart: unless-stopped
volumes:
- ./services/updater_scheduler/:/usr/src/app
depends_on:
- nats
- scheduler_mongo
environment:
- WAIT_HOSTS=nats:4222,scheduler_mongo:27017
- NATS_URI=nats://nats:4222
- MONGO_URI=mongodb://scheduler_mongo:27017
- STUDENT_NUMBERS=./all_student_numbers.txt
- ACTIVE_STUDENTS=./active_student_numbers.txt
- OODI_ADDR=https://oodikone.cs.helsinki.fi/oodi
- TOKEN=toskab1gs8cret5
- LOG_HOST=toska.cs.helsinki.fi
- LOG_PORT=9501
- LOG_HOSTNAME=updater_scheduler
- PORT=3678
container_name: updater_scheduler
analytics:
build:
context: services/oodikone2-analytics
args:
NODE_ENV: 'development'
command: ['sh', '-c', 'cp -r /usr/src/cache/node_modules/. /usr/src/app/node_modules/ && /wait && npm run dev']
restart: unless-stopped
volumes:
- ./services/oodikone2-analytics/:/usr/src/app
ports:
- 4568:4568
environment:
WAIT_HOSTS: analytics_db:5432,analytics_redis:6379
REDIS: analytics_redis
DB_URL: postgres://postgres@analytics_db:5432/analytics_db
TEST_DB: postgres://postgres@analytics_db:5432/analytics_db_test
- DB_URL=postgres://postgres@analytics_db:5432/analytics_db
- TEST_DB=postgres://postgres@analytics_db:5432/analytics_db_test
depends_on:
- analytics_db
- analytics_redis
container_name: analytics
analytics_redis:
image: redis
command: ["redis-server", "--appendonly", "yes"]
ports:
- "6380:6379"
volumes:
- ./analytics-redis-data:/data
container_name: analytics_redis
adminer:
image: adminer:4.6.2
environment:
- ADMINER_DESIGN=pepa-linha
volumes:
- ./adminer-plugins:/var/www/html/plugins-enabled
ports:
- 5050:8080
restart: always
container_name: adminer
@@ -1,9 +1,14 @@
version: '3'
version: '3.2'
services:
backend:
environment:
DB_URL: postgres://postgres@db:5432/tkt_oodi_real
DB_URL_KONE: postgres://postgres@db_kone:5432/db_kone_real
userservice:
environment:
DB_URL: postgres://postgres@user_db:5432/user_db_real
updater_writer:
environment:
DB_URL: postgres://postgres@db:5432/tkt_oodi_real
+163
View File
@@ -0,0 +1,163 @@
version: '3.2'
services:
user_db:
environment:
- POSTGRES_MULTIPLE_DATABASES=user_db,user_db_real
restart: unless-stopped
db:
environment:
- POSTGRES_MULTIPLE_DATABASES=tkt_oodi,tkt_oodi_test,tkt_oodi_real
restart: unless-stopped
backend:
build:
args:
NODE_ENV: 'development'
command: ['sh', '-c', 'cp -r /usr/src/cache/node_modules/. /usr/src/app/node_modules/ && npm run dev']
environment:
FRONT_URL: http://localhost:8000
volumes:
- ./services/backend/oodikone2-backend/:/usr/src/app
- ./services/backend/shared/models:/usr/src/app/src/models
- ./services/backend/shared/migrations:/usr/src/app/src/database/migrations
- ./services/backend/shared/migrations_kone:/usr/src/app/src/database/migrations_kone
restart: unless-stopped
frontend:
build:
args:
NODE_ENV: 'development'
command: ['sh', '-c', 'cp -r /usr/src/cache/node_modules/. /usr/src/app/node_modules/ && npm run docker']
ports:
- "8081:8081"
- "7777:7777"
environment:
USER_ADMINER_URL: http://localhost:5050/?pgsql=user_db&username=postgres
ANALYTICS_ADMINER_URL: http://localhost:5050/?pgsql=analytics_db&username=postgres
USAGE_ADMINER_URL: http://localhost:5050/?pgsql=usage_db&username=postgres
KONE_ADMINER_URL: http://localhost:5050/?pgsql=db_kone&username=postgres
volumes:
- ./services/oodikone2-frontend/:/usr/src/app
restart: unless-stopped
userservice:
build:
args:
NODE_ENV: 'development'
command: ['sh', '-c', 'cp -r /usr/src/cache/node_modules/. /usr/src/app/node_modules/ && npm run dev']
volumes:
- ./services/oodikone2-userservice/:/usr/src/app
restart: unless-stopped
usageservice:
build:
args:
NODE_ENV: 'development'
command: ['sh', '-c', 'cp -r /usr/src/cache/node_modules/. /usr/src/app/node_modules/ && npm run dev']
volumes:
- ./services/oodikone2-usageservice/:/usr/src/app
restart: unless-stopped
updater_api:
build:
args:
NODE_ENV: 'development'
command: ['sh', '-c', 'cp -r /usr/src/cache/node_modules/. /usr/src/app/node_modules/ && npm run dev']
volumes:
- ./services/updater_api/:/usr/src/app
restart: unless-stopped
updater_writer:
build:
args:
NODE_ENV: 'development'
command: ['sh', '-c', 'cp -r /usr/src/cache/node_modules/. /usr/src/app/node_modules/ && npm run dev']
volumes:
- ./services/backend/updater_writer/:/usr/src/app
- ./services/backend/shared/models:/usr/src/app/models
- ./services/backend/shared/migrations:/usr/src/app/database/migrations
- ./services/backend/shared/migrations_kone:/usr/src/app/database/migrations_kone
environment:
DB_SCHEMA_KONE: kone_data
restart: unless-stopped
updater_scheduler:
build:
args:
NODE_ENV: 'development'
command: ['sh', '-c', 'cp -r /usr/src/cache/node_modules/. /usr/src/app/node_modules/ && npm run dev']
volumes:
- ./services/updater_scheduler/:/usr/src/app
restart: unless-stopped
analytics:
build:
args:
NODE_ENV: 'development'
command: ['sh', '-c', 'cp -r /usr/src/cache/node_modules/. /usr/src/app/node_modules/ && npm run dev']
volumes:
- ./services/oodikone2-analytics/:/usr/src/app
restart: unless-stopped
adminer:
image: adminer:4.6.2
environment:
- ADMINER_DESIGN=pepa-linha
volumes:
- ./adminer-plugins:/var/www/html/plugins-enabled
ports:
- 5050:8080
container_name: adminer
restart: unless-stopped
# zookeeper:
# image: wurstmeister/zookeeper
# ports:
# - "2181:2181"
# environment:
# - KAFKA_BROKER_ID=1
# container_name: zookeeper
# kafka:
# image: wurstmeister/kafka
# container_name: kafka
# depends_on:
# - zookeeper
# ports:
# - "9092:9092"
# environment:
# - HOSTNAME_COMMAND=route -n | awk '/UG[ \t]/{print $$2}'
# - KAFKA_ZOOKEEPER_CONNECT=zookeeper:2181
# - KAFKA_AUTO_CREATE_TOPICS_ENABLE=true
# - KAFKA_DELETE_TOPIC_ENABLE=true
# - KAFKA_CREATE_TOPICS=studentnumbers:1:1,priority_studentnumbers:1:1
# - KAFKA_LOG_DIRS=/kafka/kafka-logs-1
# volumes:
# - ./kafka/docker.sock:/var/run/docker.sock
# - ./kafka/logs:/kafka/kafka-logs-1
# mongo_db:
# image: mongo
# volumes:
# - ./backups/mongo/oodilearn:/dump
# - ./mongodata:/data/db
# ports:
# - "27017:27017"
# container_name: mongo_db
# oodilearn:
# build:
# context: services/oodilearn/server
# dockerfile: Dockerfile
# volumes:
# - ./services/oodilearn/data:/data
# - ./services/oodilearn/server:/src
# - ./services/oodilearn/models:/models
# ports:
# - "5000:5000"
# environment:
# - ENV=development
# - MONGO_URI=mongodb://mongo_db:27017/oodilearn
# container_name: oodilearn
+103
View File
@@ -0,0 +1,103 @@
version: '3.2'
services:
user_db:
environment:
- POSTGRES_DB=user_db
db:
environment:
- POSTGRES_MULTIPLE_DATABASES=tkt_oodi,tkt_oodi_test
backend:
image: toska/oodikone2-backend:${TAG}
build:
cache_from:
- toska/oodikone2-backend:trunk
- toska/oodikone2-backend:staging
- toska/oodikone2-backend:latest
ports:
- "9229:9229"
environment:
FRONT_URL: http://localhost:1337
ANALYTICS_ADMINER_URL: http://localhost:5050/?pgsql=analytics_db&username=postgres
frontend:
image: toska/oodikone2-frontend:${TAG}
build:
args:
BASE_PATH: /
SENTRY_URL: ${SENTRY_URL}
SENTRY_AUTH_TOKEN: ${SENTRY_AUTH_TOKEN}
SENTRY_ORG: sentry
SENTRY_PROJECT: oodifront
cache_from:
- toska/oodikone2-frontend:trunk
- toska/oodikone2-frontend:staging
- toska/oodikone2-frontend:latest
ports:
- "5000:5000"
userservice:
image: toska/oodikone2-userservice:${TAG}
build:
cache_from:
- toska/oodikone2-userservice:trunk
- toska/oodikone2-userservice:staging
- toska/oodikone2-userservice:latest
usageservice:
image: toska/oodikone2-usageservice:${TAG}
build:
cache_from:
- toska/oodikone2-usageservice:trunk
- toska/oodikone2-usageservice:staging
- toska/oodikone2-usageservice:latest
updater_api:
image: toska/updater_api:${TAG}
build:
cache_from:
- toska/updater_api:trunk
- toska/updater_api:staging
- toska/updater_api:latest
updater_writer:
image: toska/updater_writer:${TAG}
build:
cache_from:
- toska/updater_writer:trunk
- toska/updater_writer:staging
- toska/updater_writer:latest
updater_scheduler:
image: toska/updater_scheduler:${TAG}
build:
cache_from:
- toska/updater_scheduler:trunk
- toska/updater_scheduler:staging
- toska/updater_scheduler:latest
analytics:
image: toska/oodikone2-analytics:${TAG}
build:
cache_from:
- toska/oodikone2-analytics:trunk
- toska/oodikone2-analytics:staging
- toska/oodikone2-analytics:latest
nginx:
image: nginx:latest
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- ./nginx/error.log:/etc/nginx/error_log.log
- ./nginx/log:/var/log/nginx/localhost.error_log
- ./nginx/cache/:/etc/nginx/cache
ports:
- 1337:80
depends_on:
- frontend
- backend
- userservice
- analytics
container_name: nginx
+1
View File
@@ -4,6 +4,7 @@ http {
rewrite_log on;
error_log /var/log/nginx/localhost.error_log notice;
access_log off;
server {
listen 80;
-19
View File
@@ -1,19 +0,0 @@
events { worker_connections 1024; }
http {
rewrite_log on;
error_log /var/log/nginx/localhost.error_log notice;
server {
listen 80;
location / {
proxy_pass http://frontend:5000/;
}
location /api/ {
proxy_pass http://backend:8080/;
}
}
}
+112 -96
View File
@@ -48,9 +48,9 @@
}
},
"ajv": {
"version": "6.10.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz",
"integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==",
"version": "6.10.2",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz",
"integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==",
"dev": true,
"requires": {
"fast-deep-equal": "^2.0.1",
@@ -77,6 +77,12 @@
"integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
"dev": true
},
"arch": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/arch/-/arch-2.1.1.tgz",
"integrity": "sha512-BLM56aPo9vLLFVa8+/+pJLnrZ7QGGTVHWsCwieAWT9o9K8UeGaQbzZbGoabWLOo2ksBCztoXdqBZBplqLDDCSg==",
"dev": true
},
"argparse": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
@@ -102,12 +108,12 @@
"dev": true
},
"async": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/async/-/async-2.4.0.tgz",
"integrity": "sha1-SZAgDxjqW4N8LMT4wDGmmFw4VhE=",
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz",
"integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==",
"dev": true,
"requires": {
"lodash": "^4.14.0"
"lodash": "^4.17.10"
}
},
"asynckit": {
@@ -341,9 +347,9 @@
"dev": true
},
"combined-stream": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz",
"integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==",
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"dev": true,
"requires": {
"delayed-stream": "~1.0.0"
@@ -380,9 +386,9 @@
}
},
"concurrently": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/concurrently/-/concurrently-4.1.0.tgz",
"integrity": "sha512-pwzXCE7qtOB346LyO9eFWpkFJVO3JQZ/qU/feGeaAHiX1M3Rw3zgXKc5cZ8vSH5DGygkjzLFDzA/pwoQDkRNGg==",
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/concurrently/-/concurrently-4.1.1.tgz",
"integrity": "sha512-48+FE5RJ0qc8azwKv4keVQWlni1hZeSjcWr8shBelOBtBHcKj1aJFM9lHRiSc1x7lq416pkvsqfBMhSRja+Lhw==",
"dev": true,
"requires": {
"chalk": "^2.4.1",
@@ -403,9 +409,9 @@
"dev": true
},
"rxjs": {
"version": "6.5.1",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.1.tgz",
"integrity": "sha512-y0j31WJc83wPu31vS1VlAFW5JGrnGC+j+TtGAa1fRQphy48+fDYiDmX8tjGloToEsMkxnouOg/1IzXGKkJnZMg==",
"version": "6.5.2",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.2.tgz",
"integrity": "sha512-HUb7j3kvb7p7eCUHE3FqjoDsC1xfZQ4AHFWfTKSpZ+sAhhz5X1WX0ZuUqWbzB2QhSLp3DoLUG+hMdEDKqWo2Zg==",
"dev": true,
"requires": {
"tslib": "^1.9.0"
@@ -454,41 +460,49 @@
}
},
"cypress": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/cypress/-/cypress-3.2.0.tgz",
"integrity": "sha512-PN0wz6x634QyNL56/voTzJoeScDfwtecvSfFTHfv5MkHuECVSR4VQcEZTvYtKWln3CMBMUkWbBKPIwwu2+a/kw==",
"version": "3.4.1",
"resolved": "https://registry.npmjs.org/cypress/-/cypress-3.4.1.tgz",
"integrity": "sha512-1HBS7t9XXzkt6QHbwfirWYty8vzxNMawGj1yI+Fu6C3/VZJ8UtUngMW6layqwYZzLTZV8tiDpdCNBypn78V4Dg==",
"dev": true,
"requires": {
"@cypress/listr-verbose-renderer": "0.4.1",
"@cypress/xvfb": "1.2.4",
"arch": "2.1.1",
"bluebird": "3.5.0",
"cachedir": "1.3.0",
"chalk": "2.4.2",
"check-more-types": "2.24.0",
"commander": "2.15.1",
"common-tags": "1.8.0",
"debug": "3.1.0",
"debug": "3.2.6",
"execa": "0.10.0",
"executable": "4.1.1",
"extract-zip": "1.6.7",
"fs-extra": "4.0.1",
"getos": "3.1.0",
"glob": "7.1.3",
"fs-extra": "5.0.0",
"getos": "3.1.1",
"is-ci": "1.2.1",
"is-installed-globally": "0.1.0",
"lazy-ass": "1.6.0",
"listr": "0.12.0",
"lodash": "4.17.11",
"lodash": "4.17.15",
"log-symbols": "2.2.0",
"minimist": "1.2.0",
"moment": "2.24.0",
"ramda": "0.24.1",
"request": "2.88.0",
"request-progress": "0.4.0",
"request-progress": "3.0.0",
"supports-color": "5.5.0",
"tmp": "0.0.33",
"tmp": "0.1.0",
"url": "0.11.0",
"yauzl": "2.10.0"
},
"dependencies": {
"lodash": {
"version": "4.17.15",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
"dev": true
}
}
},
"dashdash": {
@@ -507,12 +521,12 @@
"dev": true
},
"debug": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
"version": "3.2.6",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
"integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
"dev": true,
"requires": {
"ms": "2.0.0"
"ms": "^2.1.1"
}
},
"decamelize": {
@@ -630,6 +644,12 @@
"ms": "2.0.0"
}
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
"dev": true
},
"yauzl": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz",
@@ -705,13 +725,13 @@
}
},
"fs-extra": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.1.tgz",
"integrity": "sha1-f8DGyJV/mD9X8waiTlud3Y0N2IA=",
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-5.0.0.tgz",
"integrity": "sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ==",
"dev": true,
"requires": {
"graceful-fs": "^4.1.2",
"jsonfile": "^3.0.0",
"jsonfile": "^4.0.0",
"universalify": "^0.1.0"
}
},
@@ -740,12 +760,12 @@
"dev": true
},
"getos": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/getos/-/getos-3.1.0.tgz",
"integrity": "sha512-i9vrxtDu5DlLVFcrbqUqGWYlZN/zZ4pGMICCAcZoYsX3JA54nYp8r5EThw5K+m2q3wszkx4Th746JstspB0H4Q==",
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/getos/-/getos-3.1.1.tgz",
"integrity": "sha512-oUP1rnEhAr97rkitiszGP9EgDVYnmchgFzfqRzSkgtfv7ai6tEi7Ko8GgjNXts7VLWEqrTWyhsOKLe5C5b/Zkg==",
"dev": true,
"requires": {
"async": "2.4.0"
"async": "2.6.1"
}
},
"getpass": {
@@ -758,9 +778,9 @@
}
},
"glob": {
"version": "7.1.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
"integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
"version": "7.1.4",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz",
"integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==",
"dev": true,
"requires": {
"fs.realpath": "^1.0.0",
@@ -781,9 +801,9 @@
}
},
"graceful-fs": {
"version": "4.1.15",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz",
"integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==",
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.0.tgz",
"integrity": "sha512-jpSvDPV4Cq/bgtpndIWbI5hmYxhQGHPC4d4cqBPb4DLniCfhJokdXhwhaDuLBGLQdvvRum/UiX6ECVIPvDXqdg==",
"dev": true
},
"har-schema": {
@@ -923,9 +943,9 @@
}
},
"inherits": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"dev": true
},
"ini": {
@@ -1075,9 +1095,9 @@
"dev": true
},
"jsonfile": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-3.0.1.tgz",
"integrity": "sha1-pezG9l9T9mLEQVx2daAzHQmS7GY=",
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
"integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
"dev": true,
"requires": {
"graceful-fs": "^4.1.6"
@@ -1266,9 +1286,9 @@
}
},
"lodash": {
"version": "4.17.11",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
"integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==",
"version": "4.17.15",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
"dev": true
},
"lodash.once": {
@@ -1317,18 +1337,18 @@
}
},
"mime-db": {
"version": "1.39.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.39.0.tgz",
"integrity": "sha512-DTsrw/iWVvwHH+9Otxccdyy0Tgiil6TWK/xhfARJZF/QFhwOgZgOIvA2/VIGpM8U7Q8z5nDmdDWC6tuVMJNibw==",
"version": "1.40.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz",
"integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==",
"dev": true
},
"mime-types": {
"version": "2.1.23",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.23.tgz",
"integrity": "sha512-ROk/m+gMVSrRxTkMlaQOvFmFmYDc7sZgrjjM76abqmd2Cc5fCV7jAMA5XUccEtJ3cYiYdgixUVI+fApc2LkXlw==",
"version": "2.1.24",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz",
"integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==",
"dev": true,
"requires": {
"mime-db": "~1.39.0"
"mime-db": "1.40.0"
}
},
"mimic-fn": {
@@ -1376,9 +1396,9 @@
"dev": true
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true
},
"nice-try": {
@@ -1387,12 +1407,6 @@
"integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
"dev": true
},
"node-eta": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/node-eta/-/node-eta-0.1.1.tgz",
"integrity": "sha1-QGYQmzk3HHYccrfr2pqeoKXeEh8=",
"dev": true
},
"normalize-package-data": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
@@ -1523,12 +1537,6 @@
}
}
},
"os-tmpdir": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
"dev": true
},
"p-defer": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz",
@@ -1654,15 +1662,15 @@
}
},
"process-nextick-args": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
"integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==",
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
"dev": true
},
"psl": {
"version": "1.1.31",
"resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz",
"integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==",
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/psl/-/psl-1.2.0.tgz",
"integrity": "sha512-GEn74ZffufCmkDDLNcl3uuyF/aSD6exEyh1v/ZSdAomB82t6G9hzJVRx0jBmLDW+VfZqks3aScmMw9DszwUalA==",
"dev": true
},
"pump": {
@@ -1771,13 +1779,12 @@
}
},
"request-progress": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/request-progress/-/request-progress-0.4.0.tgz",
"integrity": "sha1-wZVOOQhqqFJpxWYLzuAUKmpw1+c=",
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/request-progress/-/request-progress-3.0.0.tgz",
"integrity": "sha1-TKdUCBx/7GP1BeT6qCWqBs1mnb4=",
"dev": true,
"requires": {
"node-eta": "^0.1.1",
"throttleit": "^0.0.2"
"throttleit": "^1.0.0"
}
},
"require-directory": {
@@ -1817,6 +1824,15 @@
"onetime": "^1.0.0"
}
},
"rimraf": {
"version": "2.6.3",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
"integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
"dev": true,
"requires": {
"glob": "^7.1.3"
}
},
"run-node": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/run-node/-/run-node-1.0.0.tgz",
@@ -2013,18 +2029,18 @@
"dev": true
},
"throttleit": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/throttleit/-/throttleit-0.0.2.tgz",
"integrity": "sha1-z+34jmDADdlpe2H90qg0OptoDq8=",
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz",
"integrity": "sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw=",
"dev": true
},
"tmp": {
"version": "0.0.33",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
"integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.1.0.tgz",
"integrity": "sha512-J7Z2K08jbGcdA1kkQpJSqLF6T0tdQqpR2pnSUXsIchbPdTI9v3e85cLW0d6WDhwuAleOV71j2xWs8qMPfK7nKw==",
"dev": true,
"requires": {
"os-tmpdir": "~1.0.2"
"rimraf": "^2.6.3"
}
},
"tough-cookie": {
@@ -2052,9 +2068,9 @@
"dev": true
},
"tslib": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz",
"integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==",
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
"integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==",
"dev": true
},
"tunnel-agent": {
+24 -8
View File
@@ -2,14 +2,30 @@
"name": "oodikone",
"version": "1.0.0",
"description": "Simple CLI tool for setting up the development environment for Oodikone. The entire development environment runs inside of a Docker network that's defined in the docker-compose.yml file. The specifics of what this means for setting up the environment and accessing logs is discussed in a later section.",
"main": "run.sh",
"main": "./scripts/run.sh",
"scripts": {
"cypress:open": "CYPRESS_baseUrl=http://localhost:8081 cypress open",
"cypress:run": "CYPRESS_baseUrl=http://localhost:8081 cypress run --config video=false -P ./",
"cypress:record": "cypress run --config videoUploadOnPasses=false -P ./",
"cli": "./scripts/run.sh",
"cypress": "cypress",
"cypress:open": "cypress open --config baseUrl=http://localhost:8081/",
"cypress:run": "cypress run --config video=true,videoCompression=false,baseUrl=http://localhost:8081/",
"cypress:ci": "cypress run --config video=true,videoCompression=false,baseUrl=http://localhost:1337/",
"concurrently": "concurrently",
"test": "./run_all_tests.sh",
"test_services": "./run_service_tests.sh"
"test": "./scripts/run_all_tests.sh",
"test_services": "./scripts/run_service_tests.sh",
"lint": "./scripts/run_service_lints.sh",
"docker": "docker-compose -f docker-compose.yml -f ./docker/docker-compose.dev.yml",
"docker:real": "docker-compose -f docker-compose.yml -f ./docker/docker-compose.dev.yml -f ./docker/docker-compose.dev.real.yml",
"docker:ci": "docker-compose -f docker-compose.yml -f ./docker/docker-compose.lateste2e.yml",
"docker:build": "npm run docker -- build",
"docker:up": "npm run docker -- up -d",
"docker:up:real": "npm run docker:real -- up -d",
"docker:down": "npm run docker -- down",
"docker:logs": "npm run docker -- logs -f",
"docker:logs:backend": "npm run docker -- logs -f backend",
"docker:restart": "npm run docker -- restart",
"docker:restart:backend": "npm run docker -- restart backend",
"docker:obliterate": "docker stop $(docker ps -aq) ; docker rmi -f $(docker images -a -q) ; docker system prune -a",
"start": "npm run docker:up && npm run docker:logs"
},
"husky": {
"hooks": {
@@ -27,8 +43,8 @@
},
"homepage": "https://github.com/UniversityOfHelsinkiCS/oodikone#readme",
"devDependencies": {
"concurrently": "^4.1.0",
"cypress": "^3.2.0",
"concurrently": "^4.1.1",
"cypress": "^3.4.1",
"husky": "^1.3.1"
},
"dependencies": {}
+2 -6
View File
@@ -1,6 +1,6 @@
#!/bin/bash
source scripts.sh
source ./scripts/scripts.sh
PS3='Please enter your choice: '
@@ -26,7 +26,6 @@ options=(
"Reset real db"
"Download latest anon db"
"Download latest real db"
"Full reset"
"Quit"
)
select opt in "${options[@]}"
@@ -34,7 +33,7 @@ do
case $opt in
"e2e setup")
mopo
run_e2e_setup docker-compose.lateste2e.yml
run_e2e_setup ./docker/docker-compose.lateste2e.yml staging
;;
"Anon setup")
mopo
@@ -56,9 +55,6 @@ do
"Download latest real db")
get_oodikone_server_backup
;;
"Full reset")
purge
;;
"Quit")
break
;;
+12
View File
@@ -0,0 +1,12 @@
#!/bin/bash
# stop on first error
set -e
docker-compose exec -T backend npm run lint
docker-compose exec -T updater_writer npm run lint
docker-compose exec -T updater_api npm run lint
docker-compose exec -T updater_scheduler npm run lint
docker-compose exec -T userservice npm run lint
docker-compose exec -T frontend npm run lint
docker-compose exec -T analytics npm run lint
docker-compose exec -T userservice npm run lint
@@ -3,8 +3,11 @@
# stop on first error
set -e
docker-compose exec -T backend npm test
docker-compose exec -T updater_writer npm test
docker-compose exec -T updater_api npm test
docker-compose exec -T updater_scheduler npm test
docker-compose exec -T userservice npm test
docker-compose exec -T frontend npm test
docker-compose exec -T analytics npm test
docker-compose exec -T userservice npm test
docker-compose exec -T usageservice npm test
# docker-compose exec -T updater_writer npm test
+55 -64
View File
@@ -5,9 +5,15 @@ ANONDB_DIR=anonyymioodi
BACKUP_DIR=backups
PSQL_DB_BACKUP="$ANONDB_DIR/anon.sqz"
USER_DB_BACKUP="$ANONDB_DIR/user-dump.sqz"
KONE_DB_BACKUP="$ANONDB_DIR/anon_kone.sqz"
PSQL_REAL_DB_BACKUP="$BACKUP_DIR/latest-pg.sqz"
KONE_REAL_DB_BACKUP="$BACKUP_DIR/latest-kone-pg.sqz"
USER_REAL_DB_BACKUP="$BACKUP_DIR/latest-user-pg.sqz"
docker-compose-dev () {
docker-compose -f docker-compose.yml -f ./docker/docker-compose.dev.yml "$@"
}
retry () {
for i in {1..60}
do
@@ -25,20 +31,9 @@ echo_path () {
echo $(pwd)
}
purge () {
docker-compose down || echo "docker-compose down failed"
git clean -f -fdX
}
megapurge () {
git clean -f -fdX
docker stop $(docker ps -q)
docker container prune
docker rmi $(docker images -q)
}
get_oodikone_server_backup() {
scp -r -o ProxyCommand="ssh -W %h:%p melkki.cs.helsinki.fi" oodikone.cs.helsinki.fi:/home/tkt_oodi/backups/* "$BACKUP_DIR/"
scp -r -o ProxyCommand="ssh -W %h:%p melkinpaasi.cs.helsinki.fi" oodikone.cs.helsinki.fi:/home/tkt_oodi/backups/* "$BACKUP_DIR/"
scp -r -o ProxyCommand="ssh -W %h:%p melkinpaasi.cs.helsinki.fi" svm-77.cs.helsinki.fi:/home/tkt_oodi/backups/* "$BACKUP_DIR/"
}
get_anon_oodikone() {
@@ -55,19 +50,8 @@ get_anon_oodikone() {
}
restore_psql_from_backup () {
time pg_restore -U postgres -h localhost -p 5421 --no-owner -F c --dbname=tkt_oodi -j4 $PSQL_DB_BACKUP
}
restore_real_psql_from_backup () {
time pg_restore -U postgres -h localhost -p 5421 --no-owner -F c --dbname=tkt_oodi_real -j4 $PSQL_REAL_DB_BACKUP
}
restore_userdb_from_backup () {
time pg_restore -U postgres -h localhost -p 5422 --no-owner -F c --dbname=user_db -j4 $USER_DB_BACKUP
}
restore_real_userdb_from_backup () {
time pg_restore -U postgres -h localhost -p 5422 --no-owner -F c --dbname=user_db_real -j4 $USER_REAL_DB_BACKUP
docker cp $1 $2:/asd.sqz
docker exec $2 pg_restore -U postgres --no-owner -F c --dbname=$3 -j4 /asd.sqz
}
# oodilearn
@@ -76,19 +60,28 @@ restore_real_userdb_from_backup () {
# }
ping_psql () {
echo "Pinging psql in container $1 with db name $2"
drop_psql $1 $2
echo "Creating psql in container $1 with db name $2"
retry docker exec -u postgres $1 pg_isready --dbname=$2
docker exec -u postgres $1 psql -c "CREATE DATABASE $2" || echo "container $1 DB $2 already exists"
}
drop_psql () {
echo "Dropping psql in container $1 with db name $2"
retry docker exec -u postgres $1 pg_isready --dbname=$2
docker exec -u postgres $1 psql -c "DROP DATABASE $2" || echo "container $1 DB $2 doesn't exists"
}
db_setup_full () {
echo "Restoring PostgreSQL from backup"
retry restore_real_psql_from_backup
ping_psql "oodi_db" "tkt_oodi_real"
restore_psql_from_backup $PSQL_REAL_DB_BACKUP oodi_db tkt_oodi_real
ping_psql "db_kone" "db_kone_real"
restore_psql_from_backup $KONE_REAL_DB_BACKUP db_kone db_kone_real
ping_psql "oodi_user_db" "user_db_real"
restore_psql_from_backup $USER_REAL_DB_BACKUP oodi_user_db user_db_real
# echo "Restoring MongoDB from backup"
# retry restore_mongodb_from_backup
echo "Restore user db from backup"
ping_psql "oodi_user_db" "user_db_real"
retry restore_real_userdb_from_backup
echo "Database setup finished"
}
@@ -96,47 +89,45 @@ db_anon_setup_full () {
echo "Restoring PostgreSQL from backup"
ping_psql "oodi_db" "tkt_oodi"
ping_psql "oodi_db" "tkt_oodi_test"
retry restore_psql_from_backup
restore_psql_from_backup $PSQL_DB_BACKUP oodi_db tkt_oodi
ping_psql "db_kone" "db_kone"
ping_psql "db_kone" "db_kone_test"
restore_psql_from_backup $KONE_DB_BACKUP db_kone db_kone
ping_psql "oodi_user_db" "user_db"
restore_psql_from_backup $USER_DB_BACKUP oodi_user_db user_db
# echo "Restoring MongoDB from backup"
# retry restore_mongodb_from_backup
echo "Restore user db from backup"
ping_psql "oodi_user_db" "user_db"
retry restore_userdb_from_backup
echo "Database setup finished"
}
reset_real_db () {
docker-compose down
docker-compose up -d db user_db
ping_psql "oodi_db" "tkt_oodi_real"
docker exec -u postgres oodi_db dropdb "tkt_oodi_real"
ping_psql "oodi_user_db" "user_db_real"
docker exec -u postgres oodi_user_db dropdb "user_db_real"
docker-compose-dev down
docker-compose-dev up -d db user_db db_kone
db_setup_full
docker-compose down
docker-compose-dev down
}
reset_db () {
docker-compose down
docker-compose up -d db user_db
ping_psql "oodi_db" "tkt_oodi"
docker exec -u postgres oodi_db dropdb "tkt_oodi"
ping_psql "oodi_db" "tkt_oodi_test"
docker exec -u postgres oodi_db dropdb "tkt_oodi_test"
ping_psql "oodi_user_db" "user_db"
docker exec -u postgres oodi_user_db dropdb "user_db"
docker-compose-dev down
docker-compose-dev up -d db user_db db_kone
db_anon_setup_full
docker-compose down
docker-compose-dev down
}
reset_db_for_cypress () {
# stop any service with connections to DB
docker-compose stop backend updater_writer
db_anon_setup_full
# restart services, run migrations
docker-compose restart backend updater_writer
# wait until backend is up
retry curl --silent --fail localhost:8080/ping
}
install_cli_npm_packages () {
npm ci
}
docker_build () {
docker-compose up -d --build
}
show_instructions () {
cat ./assets/instructions.txt
}
@@ -151,12 +142,12 @@ run_full_setup () {
echo "Getting anon backups from the private repository. "
get_anon_oodikone
echo "Building images"
docker-compose build
docker-compose-dev build
echo "Setup oodikone db from dump."
docker-compose up -d db user_db
docker-compose-dev up -d db user_db db_kone
db_setup_full
db_anon_setup_full
docker-compose down
docker-compose-dev down
show_instructions
}
@@ -168,11 +159,11 @@ run_anon_full_setup () {
echo "Getting anon backups from the private repository. "
get_anon_oodikone
echo "Building images"
docker-compose build
docker-compose-dev build
echo "Setup oodikone db from dump."
docker-compose up -d db user_db
docker-compose-dev up -d db user_db db_kone
db_anon_setup_full
docker-compose down
docker-compose-dev down
show_instructions
}
@@ -184,10 +175,10 @@ run_e2e_setup () {
echo "Getting anon backups from the private repository. "
get_anon_oodikone
echo "Building images"
docker-compose -f $1 build
TAG=$2 SENTRY_RELEASE_VERSION=$3 docker-compose -f docker-compose.yml -f $1 build
echo "Setup oodikone db from dump."
docker-compose -f $1 up -d db user_db
TAG=$2 SENTRY_RELEASE_VERSION=$3 docker-compose -f docker-compose.yml -f $1 up -d db user_db db_kone
db_anon_setup_full
echo "Starting services."
docker-compose -f $1 up -d
TAG=$2 SENTRY_RELEASE_VERSION=$3 docker-compose -f docker-compose.yml -f $1 up -d
}
@@ -23,7 +23,6 @@
"error",
"never"
],
"no-console": 0,
"max-len": [2, 120]
"no-console": 0
}
}
+14 -15
View File
@@ -1,22 +1,21 @@
FROM node:10.15-alpine
WORKDIR /usr/src/app
EXPOSE 8080
CMD npm start
COPY ./oodikone2-backend/package.json /usr/src/app/package.json
COPY ./oodikone2-backend/package-lock.json /usr/src/app/package-lock.json
COPY ./oodikone2-backend/package.json /usr/src/cache/package.json
COPY ./oodikone2-backend/package-lock.json /usr/src/cache/package-lock.json
RUN npm ci
ARG NODE_ENV=production
ENV NODE_ENV=${NODE_ENV}
RUN if [ "${NODE_ENV}" != "production" ]; then cp -r /usr/src/app/node_modules /usr/src/cache/node_modules; fi
COPY ./oodikone2-backend /usr/src/app
COPY ./shared/models /usr/src/app/src/models
COPY ./shared/migrations /usr/src/app/src/database/migrations
COPY ./shared/migrations_kone /usr/src/app/src/database/migrations_kone
WORKDIR /usr/src/app
RUN npm ci
COPY ./oodikone2-backend/package.json /usr/src/cache/package.json
COPY ./oodikone2-backend/package-lock.json /usr/src/cache/package-lock.json
ARG NODE_ENV=production
ENV NODE_ENV=${NODE_ENV}
RUN if [ "${NODE_ENV}" != "production" ]; then cp -r /usr/src/app/node_modules /usr/src/cache/node_modules; fi
ADD https://github.com/ufoscout/docker-compose-wait/releases/download/2.5.0/wait /wait
RUN chmod +x /wait
EXPOSE 8080
CMD /wait && npm start
File diff suppressed because it is too large Load Diff
+23 -21
View File
@@ -15,7 +15,8 @@
"docker_local": "NODE_ENV=docker_local nodemon index.js",
"dev": "NODE_ENV=dev nodemon --max_old_space_size=4096 index.js",
"anon": "NODE_ENV=test nodemon index.js",
"test": "NODE_ENV=test jest --runInBand --verbose",
"test": "npm run lint && npm run jest",
"jest": "NODE_ENV=test jest --runInBand --verbose",
"test_docker": "docker exec -t backend /bin/bash -c 'npm test'",
"update_database_dev": "NODE_ENV=dev node src/services/doo_api_database_updater/run_updater.js",
"update_database": "node src/services/doo_api_database_updater/run_updater.js",
@@ -23,7 +24,7 @@
"init_redis": "node src/util/init_redis.js",
"seed_redis": "node src/util/add_json_duplicates_to_redis.js && node src/util/map_course_codes.js",
"studentnumbers_to_file": "NODE_ENV=dev node src/services/doo_api_database_updater/db_studentnumbers_to_file.js",
"lint": "eslint --parser babel-eslint src",
"lint": "eslint --parser babel-eslint .",
"force_sync_database": "node scripts/force_sync_database.js",
"update_studentnumbers_dev": "NODE_ENV=dev node src/services/doo_api_database_updater/student_list_updater.js",
"anonymize": "node src/anonymizer/anonymizer.js",
@@ -38,41 +39,42 @@
"author": "Matti Luukkainen",
"license": "MIT",
"dependencies": {
"async-lock": "^1.2.2",
"axios": "^0.19.0",
"bluebird": "^3.5.3",
"body-parser": "^1.18.3",
"bluebird": "^3.5.5",
"body-parser": "^1.19.0",
"cors": "^2.8.5",
"dotenv": "^6.1.0",
"express": "^4.16.4",
"jsonwebtoken": "^8.4.0",
"kafka-node": "^4.1.1",
"lodash": "^4.17.10",
"cron": "^1.7.1",
"dotenv": "^6.2.0",
"express": "^4.17.1",
"jsonwebtoken": "^8.5.1",
"kafka-node": "^4.1.3",
"lodash": "^4.17.15",
"mkdirp": "^0.5.1",
"moment": "^2.22.2",
"moment": "^2.24.0",
"morgan": "^1.9.1",
"node-nats-streaming": "^0.2.2",
"nodemailer": "^4.7.0",
"pg": "^7.7.1",
"pg": "^7.11.0",
"raven": "^2.6.3",
"redis": "^2.8.0",
"sequelize": "^5.3.0",
"sequelize": "^5.10.2",
"umzug": "^2.2.0",
"uuid": "^3.3.2",
"winston": "^3.0.0",
"winston-log2gelf": "^2.0.4",
"winston-transport": "^4.2.0"
"winston-transport": "^4.3.0"
},
"devDependencies": {
"ava": "^0.25.0",
"ava": "^2.2.0",
"babel-eslint": "^8.2.6",
"eslint": "^5.9.0",
"eslint": "^5.16.0",
"faker": "^4.1.0",
"jest": "^24.1.0",
"nock": "^10.0.2",
"jest": "^24.8.0",
"nock": "^10.0.6",
"node-status": "^1.0.0",
"nodemon": "^1.18.7",
"nyc": "^13.1.0",
"supertest": "^3.1.0"
"nodemon": "^1.19.1",
"nyc": "^13.3.0",
"supertest": "^3.4.2"
},
"ava": {
"files": [
@@ -13,9 +13,10 @@ axios.defaults.auth = {
username: 'tktl',
}
axios.defaults.params = {
token: process.env.TOKEN
}
instance.interceptors.request.use((config) => {
config.params = {token: process.env.TOKEN}
return config
})
const getStudent = (studentNumber) => {
return instance.get(`${process.env.OODI_ADDR}/students/${studentNumber}/info`)
+30 -20
View File
@@ -4,33 +4,43 @@ const bodyParser = require('body-parser')
const Raven = require('raven')
const conf = require('./conf-backend')
const routes = require('./routes')
const { StartNats } = require('./events')
const { startCron } = require('./events')
const { PORT } = conf
const app = express()
const { initializeDatabaseConnection } = require('./database/connection')
StartNats()
initializeDatabaseConnection().then(() => {
const app = express()
Raven.config(process.env.SENTRY_ADDR, { captureUnhandledRejections: true }).install()
startCron()
app.use(cors({ credentials: true, origin: conf.frontend_addr }))
app.use(bodyParser.json())
Raven.config(process.env.SENTRY_ADDR, { captureUnhandledRejections: true }).install()
app.get('/ping', async (req, res) => {
res.json({ data: 'pong' })
})
app.use(cors({ credentials: true, origin: conf.frontend_addr }))
app.use(bodyParser.json())
let BASE_URL = ''
if (process.env.NODE_ENV === 'dev' || process.env.NODE_ENV === 'test') {
BASE_URL = '/api'
}
app.get('/ping', async (req, res) => {
res.json({ data: 'pong' })
})
routes(app, BASE_URL)
let BASE_URL = ''
if (process.env.NODE_ENV === 'dev' || process.env.NODE_ENV === 'test') {
BASE_URL = '/api'
}
app.get('*', async (req, res) => {
const results = { error: 'unknown endpoint' }
res.status(404).json(results)
})
routes(app, BASE_URL)
module.exports = app.listen(PORT, () => {
console.log('Example app listening on port ' + PORT + '!')
app.get('*', async (req, res) => {
const results = { error: 'unknown endpoint' }
res.status(404).json(results)
})
const server = app.listen(PORT, () => console.log(`Backend listening on port ${PORT}!`))
process.on('SIGTERM', () => {
server.close(() => {
console.log('Process terminated')
})
})
}).catch(e => {
process.exitCode = 1
console.log(e)
})
@@ -1,23 +1,27 @@
require('dotenv').config()
const { NODE_ENV } = process.env
let DB_URL = process.env.DB_URL
const isTest = process.env.NODE_ENV === 'test'
let DB_URL = process.env.DB_URL
let DB_URL_KONE = process.env.DB_URL_KONE
if (isTest) {
DB_URL = process.env.TEST_DB
DB_URL_KONE = process.env.TEST_DB_KONE
}
else if (NODE_ENV === 'anon') {
DB_URL = process.env.ANON_DB
DB_URL_KONE = process.env.ANON_DB_KONE
}
const frontend_addr = process.env.FRONT_URL
const redis = process.env.REDIS
const TOKEN_SECRET = process.env.TOKEN_SECRET
const DB_SCHEMA = process.env.DB_SCHEMA || 'public'
const DB_SCHEMA_KONE = process.env.DB_SCHEMA_KONE || 'kone_data'
const DB_SCHEMA_KONE = process.env.DB_SCHEMA_KONE || 'public'
const CERT_PATH = process.env.CERT_PATH // production/staging only
const KEY_PATH = process.env.KEY_PATH // production/staging only
const OODILEARN_URL = process.env.OODILEARN_URL
const USERSERVICE_URL = process.env.USERSERVICE_URL
const UPDATER_URL = process.env.UPDATER_URL
const USAGESERVICE_URL = process.env.USAGESERVICE_URL
const ANALYTICS_URL = process.env.ANALYTICS_URL
const PORT = isTest ? 8079 : 8080
@@ -58,10 +62,26 @@ if (process.env.NODE_ENV === 'dev' || isTest) {
}
module.exports = {
frontend_addr, DB_URL, redis, TOKEN_SECRET, DB_SCHEMA, DB_SCHEMA_KONE, OODI_ADDR, CERT_PATH, KEY_PATH, FEATURES, OODILEARN_URL,
USERSERVICE_URL: formatURL(USERSERVICE_URL), ACCESS_TOKEN_HEADER_KEY, PORT,
frontend_addr,
DB_URL,
DB_URL_KONE,
redis,
TOKEN_SECRET,
DB_SCHEMA,
DB_SCHEMA_KONE,
OODI_ADDR,
CERT_PATH,
KEY_PATH,
FEATURES,
OODILEARN_URL,
USERSERVICE_URL: formatURL(USERSERVICE_URL),
ACCESS_TOKEN_HEADER_KEY,
PORT,
ANALYTICS_URL: formatURL(ANALYTICS_URL),
USAGESERVICE_URL,
requiredGroup, OODI_SECRET, OODI_SECRET_HEADER_KEY,
isTest
requiredGroup,
OODI_SECRET,
OODI_SECRET_HEADER_KEY,
isTest,
UPDATER_URL
}
@@ -5,77 +5,65 @@ const conf = require('../conf-backend')
const sequelize = new Sequelize(conf.DB_URL, {
schema: conf.DB_SCHEMA,
searchPath: conf.DB_SCHEMA,
logging: false,
operatorsAliases: false
logging: false
})
sequelize.query(`SET SESSION search_path to ${conf.DB_SCHEMA}`)
const sequelizeKone = new Sequelize(conf.DB_URL, {
const sequelizeKone = new Sequelize(conf.DB_URL_KONE, {
schema: conf.DB_SCHEMA_KONE,
searchPath: conf.DB_SCHEMA_KONE,
logging: false,
operatorsAliases: false
logging: false
})
sequelizeKone.query(`SET SESSION search_path to ${conf.DB_SCHEMA_KONE}`)
// See https://github.com/sequelize/sequelize/issues/10875
const runMigrations = async () => {
try {
const migrator = new Umzug({
storage: 'sequelize',
storageOptions: {
sequelize: sequelize,
tableName: 'migrations'
},
logging: console.log,
migrations: {
params: [
sequelize.getQueryInterface(),
Sequelize
],
path: `${process.cwd()}/src/database/migrations`,
pattern: /\.js$/,
schema: conf.DB_SCHEMA
const initializeDatabaseConnection = async () => {
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))
const waitSeconds = 60
for (let i = 1; i <= waitSeconds; i++) {
try {
await sequelize.authenticate()
await sequelizeKone.authenticate()
break
} catch (e) {
if (i === waitSeconds) {
console.log(`Could not connect to database in ${waitSeconds} seconds`)
throw e
}
})
const migrations = await migrator.up()
console.log('.')
await sleep(1000)
}
}
if (!conf.isTest) {
try {
const migrator = new Umzug({
storage: 'sequelize',
storageOptions: {
sequelize: sequelizeKone,
tableName: 'migrations',
schema: conf.DB_SCHEMA_KONE
},
logging: console.log,
migrations: {
params: [
sequelizeKone.getQueryInterface(),
Sequelize
],
path: `${process.cwd()}/src/database/migrations_kone`,
pattern: /\.js$/,
schema: conf.DB_SCHEMA_KONE
},
})
const migrations = await migrator.up()
console.log('Migrations up to date', migrations)
} catch (e) {
console.log('Migration error, message:', e)
console.log('Kone Migrations up to date', migrations)
} catch (e) {
console.log('Kone Migration error')
throw e
}
}
}
const runMigrationsKone = async () => {
try {
const migrator = new Umzug({
storage: 'sequelize',
storageOptions: {
sequelize: sequelizeKone,
tableName: 'migrations',
schema: conf.DB_SCHEMA_KONE
},
logging: console.log,
migrations: {
params: [
sequelizeKone.getQueryInterface(),
Sequelize
],
path: `${process.cwd()}/src/database/migrations_kone`,
pattern: /\.js$/,
schema: conf.DB_SCHEMA_KONE
},
})
const migrations = await migrator.up()
console.log('Kone Migrations up to date', migrations)
} catch (e) {
console.log('Kone Migration error, message:', e)
}
}
const migrationPromise = !conf.isTest ? runMigrations().then(() => runMigrationsKone()) : Promise.resolve()
const forceSyncDatabase = async () => {
try {
await sequelize.getQueryInterface().createSchema(conf.DB_SCHEMA)
@@ -94,6 +82,6 @@ const forceSyncDatabase = async () => {
module.exports = {
sequelize,
sequelizeKone,
migrationPromise,
initializeDatabaseConnection,
forceSyncDatabase
}
@@ -1,5 +1,6 @@
const fs = require('fs')
const { Migration, MigrationKone } = require('../models/index')
const { Migration } = require('../models/index')
const { MigrationKone } = require('../models/models_kone')
const DEFAULT_PATH = `${process.cwd()}/src/database/migrations`
const DEFAULT_PATH_KONE = `${process.cwd()}/src/database/migrations_kone`
+85 -101
View File
@@ -1,117 +1,101 @@
var stan = require('node-nats-streaming').connect(
'updaterNATS',
process.env.HOSTNAME,
process.env.NATS_URI
)
const { CronJob } = require('cron')
const { refreshAssociationsInRedis } = require('./services/studyrights')
const { getAllProgrammes } = require('./services/studyrights')
const { productivityStatsForStudytrack, throughputStatsForStudytrack } = require('./services/studytrack')
const { setProductivity, setThroughput, patchProductivity, patchThroughput } = require('./services/analyticsService')
const { calculateFacultyYearlyStats } = require('./services/faculties')
const { setProductivity, setThroughput, patchProductivity, patchThroughput, patchFacultyYearlyStats } = require('./services/analyticsService')
const taskStatuses = { }
const handleMessage = (asyncHandlerFunction) => async (msg) => {
const key = msg.getSubject()+'_'+msg.getData()
if (taskStatuses[key])
return
stan.publish('status', key+':RECEIVED', (err) => {
if(err) {
console.log('publish failed', err)
}
})
taskStatuses[key] = true
const success = await asyncHandlerFunction(msg)
taskStatuses[key] = false
stan.publish('status', key+(success ? ':DONE' : ':ERRORED'), (err) => {
if(err) {
console.log('publish failed', err)
}
})
msg.ack()
const schedule = (cronTime, func) => new CronJob({ cronTime, onTick: func, start: true, timeZone: 'Europe/Helsinki' })
const refreshFacultyYearlyStats = async () => {
try {
console.log('Refreshing faculty yearly stats...')
const data = await calculateFacultyYearlyStats()
await patchFacultyYearlyStats(data)
} catch (e) {
console.error(e)
}
}
const StartNats = () => {
console.log(`STARTING WITH ${process.env.HOSTNAME} as id`)
var opts = stan.subscriptionOptions()
opts.setManualAckMode(true)
// opts.setAckWait(6*60*60*1000)
// opts.setDeliverAllAvailable()
// opts.setDurableName('durable')
opts.setMaxInFlight(1)
stan.on('connect', async function() {
stan.subscribe('RefreshStudyrightAssociations', opts).on('message', handleMessage(async () => {
const refreshStudyrightAssociations = async () => {
try {
console.log('Refreshing studyright associations...')
await refreshAssociationsInRedis()
} catch (e) {
console.error(e)
}
}
const refreshOverview = async () => {
try {
console.log('Refreshing overview...')
const codes = (await getAllProgrammes()).map(p => p.code)
let ready = 0
for (const code of codes) {
try {
await refreshAssociationsInRedis()
await patchThroughput({ [code]: { status: 'RECALCULATING' } })
const since = new Date().getFullYear() - 5
const data = await throughputStatsForStudytrack(
code,
since
)
await setThroughput(
data
)
} catch (e) {
console.error(e)
return false
}
return true
}))
stan.subscribe('RefreshOverview', opts).on('message', handleMessage(async () => {
try {
console.log('RefreshOverview starting')
const codes = (await getAllProgrammes()).map(p => p.code)
let ready = 0
for(const code of codes) {
try {
await patchThroughput({ [code]: { status: 'RECALCULATING' } })
const since = new Date().getFullYear() - 5
const data = await throughputStatsForStudytrack(
code,
since
)
await setThroughput(
data
)
} catch (e) {
try {
await patchThroughput({ [code]: { status: 'RECALCULATION ERRORED' } })
} catch (e) {
console.error(
e
)
}
console.log(
`Failed to update throughput stats for code: ${code}, reason: ${
e.message
}`
)
}
try {
await patchProductivity({ [code]: { status: 'RECALCULATING' } })
const since = '2017-08-01'
const data = await productivityStatsForStudytrack(code, since)
await setProductivity(data)
} catch (e) {
try {
await patchProductivity({
[code]: { status: 'RECALCULATION ERRORED' }
})
} catch (e) {
console.error(e)
}
console.log(`Failed to update productivity stats for code: ${code}, reason: ${e.message}`)
}
ready += 1
console.log(
`RefreshOverview ${ready}/${
codes.length
} done`
try {
await patchThroughput({ [code]: { status: 'RECALCULATION ERRORED' } })
} catch (e) {
console.error(
e
)
}
} catch (e) {
console.error(e)
return false
console.log(
`Failed to update throughput stats for code: ${code}, reason: ${
e.message
}`
)
}
return true
}))
})
return stan
try {
await patchProductivity({ [code]: { status: 'RECALCULATING' } })
const since = '2017-08-01'
const data = await productivityStatsForStudytrack(code, since)
await setProductivity(data)
} catch (e) {
try {
await patchProductivity({
[code]: { status: 'RECALCULATION ERRORED' }
})
} catch (e) {
console.error(e)
}
console.error(e)
console.log(`Failed to update productivity stats for code: ${code}, reason: ${e.message}`)
}
ready += 1
console.log(
`RefreshOverview ${ready}/${
codes.length
} done`
)
}
} catch (e) {
console.error(e)
}
}
const startCron = () => {
if (process.env.NODE_ENV === 'production') {
schedule('0 6 * * *', async () => {
await refreshFacultyYearlyStats()
await refreshStudyrightAssociations()
await refreshOverview()
})
}
}
module.exports = {
StartNats
startCron
}
@@ -1,20 +1,9 @@
const morgan = require('morgan')
const UsageService = require('../services/usageService')
const accessLogger = morgan((tokens, req, res) => {
const fields = ['method', 'url', 'status', 'response-time', 'remote-addr', 'remote-user', 'user-agent', 'referrer']
const message = [
req.decodedToken.name, ':',
tokens['method'](req, res),
tokens['url'](req, res),
tokens['status'](req, res),
'-',
tokens['response-time'](req, res), 'ms'
].join(' ')
const meta = req.decodedToken
fields.forEach(field => meta[field] = tokens[field](req, res))
UsageService.log(message, meta).catch(console.log)
})
module.exports = accessLogger
@@ -1,6 +1,7 @@
const jwt = require('jsonwebtoken')
const conf = require('../conf-backend')
const blacklist = require('../services/blacklist')
const { getAccessGroupCodesFor, getCodesFromElementDetails } = require('../services/userService')
const { ACCESS_TOKEN_HEADER_KEY } = require('../conf-backend')
const { hasRequiredGroup, parseHyGroups } = require('../util/utils')
@@ -15,9 +16,11 @@ const checkAuth = async (req, res, next) => {
if (err) {
res.status(403).json(err)
} else if (decoded.version !== TOKEN_VERSION) {
res.status(401).json({ error: 'Token needs to be refreshed - invalid version', reloadPage: true })
res.status(401).json({ error: 'Token needs to be refreshed - invalid version' })
} else if (decoded.mockedBy ? isShibboUser(decoded.mockedBy, uid) : isShibboUser(decoded.userId, uid)) {
req.decodedToken = decoded
req.roles = await getAccessGroupCodesFor(decoded.userId)
req.rights = await getCodesFromElementDetails(decoded.userId)
next()
} else {
res.status(403).json({ error: 'User shibboleth id and token id did not match' })
@@ -28,17 +31,15 @@ const checkAuth = async (req, res, next) => {
}
}
const roles = requiredRoles => (req, res, next) => {
if (req.decodedToken && req.decodedToken.roles != null) {
const roles = req.decodedToken.roles.map(r => r.group_code)
console.log(`Request has roles: ${roles}`)
const roles = requiredRoles => async (req, res, next) => {
if (req.decodedToken) {
const { roles } = req
if (requiredRoles.every(r => roles.indexOf(r) >= 0) || roles.includes('admin')) {
console.log(`authorized for ${requiredRoles}`)
next()
return
}
}
console.log(`missing required roles ${requiredRoles}`)
console.log(`Missing required roles ${ requiredRoles }`)
res.status(403).json({ error: 'missing required roles' })
}
@@ -48,8 +49,7 @@ const checkRequiredGroup = async (req, res, next) => {
const tokenOutdated = req.decodedToken.enabled !== enabled
if (tokenOutdated) {
res.status(401).json({
error: 'Token needs to be refreshed - enabled doesnt match hy-group requirement',
reloadPage: true
error: 'Token needs to be refreshed - enabled doesnt match hy-group requirement'
})
} else if (!enabled) {
res.status(403).json({ error: 'User is not enabled' })
@@ -62,7 +62,7 @@ const checkUserBlacklisting = async (req, res, next) => {
const { userId, createdAt } = req.decodedToken
const isBlacklisted = await blacklist.isUserBlacklisted(userId, createdAt)
if (isBlacklisted) {
res.status(401).json({ error: 'Token needs to be refreshed - blacklisted', reloadPage: true })
res.status(401).json({ error: 'Token needs to be refreshed - blacklisted' })
} else {
next()
}
@@ -23,6 +23,7 @@ const oodi = require('./routes/oodi')
const task = require('./routes/tasks')
const feedback = require('./routes/feedback')
const tags = require('./routes/tags')
const updater = require('./routes/updater')
module.exports = (app, url) => {
app.use(url, log)
@@ -38,15 +39,16 @@ module.exports = (app, url) => {
app.use(url, providers)
app.use(url, faculties)
app.use(url, semesters)
app.use(url, tags)
app.use(`${url}/updater`, auth.roles(['admin']), updater)
app.use(`${url}/teachers`, auth.roles(['teachers']), teachers)
app.use(`${url}/users`, auth.roles(['users']), users)
app.use(`${url}/feedback`, feedback)
app.use(`${url}/usage`, auth.roles(['usage']), usage)
app.use(`${url}/oodilearn`, auth.roles(['oodilearn']), oodilearn)
app.use(`${url}/course-groups`, auth.roles(['coursegroups']), courseGroups)
app.use(`${url}/mandatory_courses`, mandatoryCourses),
app.use(`${url}/mandatory-course-labels`, mandatoryCourseLabels),
app.use(`${url}/mandatory_courses`, mandatoryCourses)
app.use(`${url}/mandatory-course-labels`, mandatoryCourseLabels)
app.use(`${url}/oodi`, auth.roles(['dev']), oodi)
app.use(url, auth.roles(['dev', 'admin']), task)
app.use(url, tags)
}
@@ -1,12 +1,11 @@
const router = require('express').Router()
const CourseGroupService = require('../services/courseGroups')
router.get('/programme/:programmeId/:force?', async (req, res) => {
const { programmeId, force } = req.params
const { rights, roles } = req.decodedToken
const { rights, roles } = req
const semesterCode = req.query.semester
if (rights.includes(programmeId) || (roles && roles.map(r => r.group_code).includes('admin'))) {
if (rights.includes(programmeId) || (roles && roles.includes('admin'))) {
const courseGroups = await CourseGroupService.getCourseGroupsWithTotals(
programmeId, semesterCode, force === 'force'
)
@@ -39,8 +39,8 @@ router.get('/coursedisciplines', async (req, res) => {
router.get('/v2/courseyearlystats', async (req, res) => {
let results = []
const { rights, roles } = req.decodedToken
const admin = roles.map(r => r.group_code).includes('admin')
const { rights, roles } = req
const admin = roles.includes('admin')
if (!admin) {
if (rights.length <= 0) {
return res.status(403).json({ error: 'No programmes so no access to course stats' })
@@ -57,19 +57,21 @@ router.get('/v2/courseyearlystats', async (req, res) => {
router.get('/v3/courseyearlystats', async (req, res) => {
try {
const { rights, roles } = req.decodedToken
const admin = roles.map(r => r.group_code).includes('admin')
const { rights, roles } = req
const admin = roles.includes('admin')
if (!admin) {
// If user has rights to see at least one programme, then they are allowed
// to see all of them
if (rights.length <= 0) {
return res.status(403).json({ error: 'No programmes so no access to course stats' })
}
}
const { codes, startyearcode, endyearcode, separate: sep } = req.query
const { codes, separate: sep } = req.query
const separate = !sep ? false : JSON.parse(sep)
if (!codes || !startyearcode) {
if (!codes) {
res.status(422).send('Missing required query parameters')
} else {
const results = await Course.courseYearlyStats(codes, separate, startyearcode, endyearcode)
const results = await Course.courseYearlyStats(codes, separate)
res.json(results)
}
} catch (e) {
@@ -1,11 +1,20 @@
const router = require('express').Router()
const { getAllDegreesAndProgrammes, getAllProgrammes } = require('../services/studyrights')
const { getAllDegreesAndProgrammes, getAllProgrammes, getAllElementDetails } = require('../services/studyrights')
const MandatoryCourses = require('../services/mandatoryCourses')
const { productivityStatsForStudytrack, throughputStatsForStudytrack } = require('../services/studytrack')
const { findProgrammeTheses, createThesisCourse, deleteThesisCourse } = require('../services/thesis')
const { getProductivity, setProductivity, getThroughput, setThroughput,
patchProductivity, patchThroughput, ping } = require('../services/analyticsService')
router.get('/elementdetails/all', async (req, res) => {
try {
const elementdetails = await getAllElementDetails()
res.json(elementdetails)
} catch (e) {
res.status(500).json(e)
}
})
router.get('/studyprogrammes', async (req, res) => {
try {
const studyrights = await getAllDegreesAndProgrammes()
@@ -89,6 +98,7 @@ router.get('/v2/studyprogrammes/productivity/recalculate', async (req, res) => {
console.error(e)
return
}
console.error(e)
console.log(`Failed to update productivity stats for code: ${code}, reason: ${e.message}`)
}
ready += 1
@@ -149,6 +159,7 @@ router.get('/v2/studyprogrammes/throughput/recalculate', async (req, res) => {
console.error(e)
return
}
console.error(e)
console.log(`Failed to update throughput stats for code: ${code}, reason: ${e.message}`)
}
ready += 1
@@ -1,9 +1,29 @@
const router = require('express').Router()
const { all } = require('../services/organisations')
const { byType: getElementDetailsByType } = require('../services/elementdetails')
const { getFacultyYearlyStats } = require('../services/analyticsService')
router.get('/faculties', async (req, res) => {
const faculties = await all()
res.json(faculties)
})
router.get('/faculties/yearlystats', async (req, res) => {
try {
const facultyYearlyStats = await getFacultyYearlyStats()
res.status(200).json(facultyYearlyStats)
} catch (e) {
res.status(400).json({ error: e })
}
})
router.get('/faculties/programmes', async (req, res) => {
try {
const facultyProgrammes = await getElementDetailsByType(20)
res.json(facultyProgrammes)
} catch (e) {
res.status(400).json({ error: e })
}
})
module.exports = router
@@ -4,56 +4,49 @@ const MandatoryCourses = require('../services/mandatoryCourses')
router.delete('/:programme', async (req, res) => {
const { programme } = req.params
const { course } = req.body
if (programme && course) {
try {
await MandatoryCourses.remove(programme, course)
res.status(200).json(course)
} catch (err) {
console.error(err)
res.status(400).json(err.message)
}
} else {
res.status(422).end()
if (!programme || !course) return res.status(400).end()
try {
await MandatoryCourses.remove(programme, course)
res.status(200).json(course)
} catch (err) {
console.error(err)
res.status(500).json(err.message)
}
})
router.post('/:programme', async (req, res) => {
const { programme } = req.params
const { course } = req.body
if (programme && course) {
try {
await MandatoryCourses.create(programme, course)
const newCourse = await MandatoryCourses.find(programme, course)
res.status(201).json({ name: newCourse.course.name, code: newCourse.course_code, label: newCourse.label })
} catch (err) {
console.error(err)
res.status(400).json(err.message)
}
} else {
res.status(422).end()
if (!programme || !course) return res.status(400).end()
try {
await MandatoryCourses.create(programme, course)
const newCourse = await MandatoryCourses.find(programme, course)
if (!newCourse) return res.status(400).end()
res.status(201).json({ name: newCourse.course.name, code: newCourse.course_code, label: newCourse.label })
} catch (err) {
console.error(err)
res.status(500).json(err.message)
}
})
router.post('/:programme/label/:course', async (req, res) => {
const { programme, course } = req.params
const { label } = req.body
if (programme && course) {
try {
await MandatoryCourses.updateLabel(programme, course, label)
const updatedCourse = await MandatoryCourses.find(programme, course)
res
.status(200)
.json({
name: updatedCourse.course.name,
code: updatedCourse.course_code,
label: updatedCourse.mandatory_course_label
})
} catch (err) {
console.error(err)
res.status(400).json(err.message)
}
} else {
res.status(422).end()
if (!programme || !course) return res.status(400).end()
try {
await MandatoryCourses.updateLabel(programme, course, label)
const updatedCourse = await MandatoryCourses.find(programme, course)
if (!updatedCourse) return res.status(400).end()
res
.status(200)
.json({
name: updatedCourse.course.name,
code: updatedCourse.course_code,
label: updatedCourse.mandatory_course_label
})
} catch (err) {
console.error(err)
res.status(500).json(err.message)
}
})
@@ -1,13 +1,17 @@
const router = require('express').Router()
const Population = require('../services/populations')
const Filters = require('../services/filters')
const { updateStudents } = require('../services/doo_api_database_updater/database_updater')
const { updateStudents } = require('../services/updaterService')
const { isValidStudentId } = require('../util/index')
const Student = require('../services/students')
const StudyrightService = require('../services/studyrights')
const UserService = require('../services/userService')
// POST instead of GET because of too long params and "sensitive" data
router.post('/v2/populationstatistics/courses', async (req, res) => {
try {
if (!req.body.year || !req.body.semesters || !req.body.studyRights) {
if (!req.body.startYear || !req.body.semesters || !req.body.studyRights) {
res.status(400).json({ error: 'The body should have a year, semester and study rights defined' })
return
}
@@ -27,28 +31,106 @@ router.post('/v2/populationstatistics/courses', async (req, res) => {
res.json(result)
} catch (e) {
res.status(400).json({ error: e })
console.log(e)
res.status(500).json({ error: e })
}
})
router.post('/v2/populationstatistics/coursesbycoursecode', async (req, res) => {
try {
if (!req.body.yearcode || !req.body.coursecodes) {
res.status(400).json({ error: 'The body should have a yearcode and coursecode defined' })
return
}
const { coursecodes, yearcode } = req.body
let studentnumberlist
const studentnumbers = await Student.findByCourseAndSemesters(coursecodes, yearcode)
const { decodedToken: { userId }, roles } = req
if (roles && roles.includes('admin')) {
studentnumberlist = studentnumbers
} else {
const unitsUserCanAccess = await UserService.getUnitsFromElementDetails(userId)
const codes = unitsUserCanAccess.map(unit => unit.id)
studentnumberlist = await Student.filterStudentnumbersByAccessrights(studentnumbers, codes)
}
const result = await Population.bottlenecksOf({
startYear: 1900,
endYear: 2200,
studyRights: [],
semesters: ['FALL', 'SPRING'],
months: 10000
}, studentnumberlist)
if (result.error) {
res.status(400).json(result)
return
}
res.json(result)
} catch (e) {
console.log(e)
res.status(500).json({ error: e })
}
})
router.post('/v2/populationstatistics/coursesbystudentnumberlist', async (req, res) => {
try {
if (!req.body.studentnumberlist) {
res.status(400).json({ error: 'The body should have a studentnumberlist defined' })
return
}
let studentnumberlist
const { decodedToken: { userId }, roles } = req
if (roles && roles.includes('admin')) {
studentnumberlist = req.body.studentnumberlist
} else {
const unitsUserCanAccess = await UserService.getUnitsFromElementDetails(userId)
const codes = unitsUserCanAccess.map(unit => unit.id)
studentnumberlist = await Student.filterStudentnumbersByAccessrights(req.body.studentnumberlist, codes)
}
const result = await Population.bottlenecksOf({
startYear: 1900,
endYear: 2200,
studyRights: [],
semesters: ['FALL', 'SPRING'],
months: 10000
}, studentnumberlist)
if (result.error) {
res.status(400).json(result)
return
}
res.json(result)
} catch (err) {
console.log(err)
res.status(500).json({ error: err })
}
})
router.get('/v3/populationstatistics', async (req, res) => {
const { year, semesters, studyRights: studyRightsJSON } = req.query
const { startYear, semesters, studyRights: studyRightsJSON } = req.query
try {
if (!year || !semesters || !studyRightsJSON) {
if (!startYear || !semesters || !studyRightsJSON) {
res.status(400).json({ error: 'The query should have a year, semester and studyRights defined' })
return
}
let studyRights = null
try {
studyRights = JSON.parse(studyRightsJSON)
const { roles, rights } = req.decodedToken
if (!roles || !roles.map(r => r.group_code).includes('admin')) {
const { rights, roles } = req
if (!roles || !roles.includes('admin')) {
if (!rights.includes(studyRights.programme)) {
res.status(403).json([])
return
}
}
} catch(e) {
} catch (e) {
console.error(e)
res.status(400).json({ error: 'The query had invalid studyRights' })
return
@@ -57,8 +139,7 @@ router.get('/v3/populationstatistics', async (req, res) => {
if (req.query.months == null) {
req.query.months = 12
}
const result = await Population.optimizedStatisticsOf({ ...req.query, studyRights})
const result = await Population.optimizedStatisticsOf({ ...req.query, studyRights })
if (result.error) {
console.log(result.error)
@@ -70,7 +151,78 @@ router.get('/v3/populationstatistics', async (req, res) => {
res.json(result)
} catch (e) {
console.log(e)
res.status(400).json({ error: e })
res.status(500).json({ error: e })
}
})
router.get('/v3/populationstatisticsbycourse', async (req, res) => {
const { coursecodes, yearcode } = req.query
if (!coursecodes || !yearcode) {
res.status(400).json({ error: 'The body should have a yearcode and coursecode defined' })
return
}
const semesters = ['FALL', 'SPRING']
let studentnumberlist
const studentnumbers = await Student.findByCourseAndSemesters(JSON.parse(coursecodes), yearcode)
const { decodedToken: { userId }, roles } = req
if (roles && roles.includes('admin')) {
studentnumberlist = studentnumbers
} else {
const unitsUserCanAccess = await UserService.getUnitsFromElementDetails(userId)
const codes = unitsUserCanAccess.map(unit => unit.id)
studentnumberlist = await Student.filterStudentnumbersByAccessrights(studentnumbers, codes)
}
try {
const result = await Population.optimizedStatisticsOf({
startYear: 1900,
endYear: 2200,
studyRights: [],
semesters,
months: 10000
}, studentnumberlist)
if (result.error) {
console.log(result.error)
res.status(400).end()
return
}
console.log(`request completed ${new Date()}`)
res.json(result)
} catch (e) {
console.log(e)
res.status(500).json({ error: e })
}
})
router.post('/v3/populationstatisticsbystudentnumbers', async (req, res) => {
const { studentnumberlist } = req.body
const { roles } = req
if (!(roles && roles.includes('admin'))) {
console.log('no rights')
res.status(400).end()
return
} else {
try {
const result = await Population.optimizedStatisticsOf({
startYear: 1900,
endYear: 2200,
studyRights: [],
semesters: ['FALL', 'SPRING'],
months: 10000
}, studentnumberlist)
if (result.error) {
console.log(result.error)
res.status(400).end()
return
}
res.status(200).json(result)
} catch (err) {
console.log(err)
res.status(400).end()
}
}
})
@@ -120,19 +272,24 @@ router.delete('/v2/populationstatistics/filters', async (req, res) => {
router.post('/updatedatabase', async (req, res) => {
const studentnumbers = req.body
console.log(studentnumbers)
if (studentnumbers) {
await updateStudents(studentnumbers, 128)
res.status(200).json('Updated')
} else {
if (!(studentnumbers && studentnumbers.every(sn => isValidStudentId(sn)))) {
res.status(400).end()
return
}
try {
const response = await updateStudents(studentnumbers)
if (response) {
res.status(200).json('Scheduled')
}
} catch (err) {
res.status(500).json(err)
}
})
router.get('/v3/populationstatistics/studyprogrammes', async (req, res) => {
try {
const { rights, roles } = req.decodedToken
if (roles && roles.map(r => r.group_code).includes('admin')) {
const { rights, roles } = req
if (roles && roles.includes('admin')) {
const studyrights = await StudyrightService.getAssociations()
res.json(studyrights)
} else {
@@ -2,8 +2,7 @@ const router = require('express').Router()
const { getSemestersAndYears } = require('../services/semesters')
router.get('/semesters/codes', async(req, res) => {
const before = new Date()
const providers = await getSemestersAndYears(before)
const providers = await getSemestersAndYears()
res.json(providers)
})
@@ -4,8 +4,9 @@ const userService = require('../services/userService')
const Unit = require('../services/units')
router.get('/students', async (req, res) => {
const { roles, userId } = req.decodedToken
if (roles && roles.map(r => r.group_code).includes('admin')) {
const { roles, decodedToken: { userId } } = req
if (roles && roles.includes('admin')) {
let results = []
if (req.query.searchTerm) {
results = await Student.bySearchTerm(req.query.searchTerm)
@@ -20,15 +21,21 @@ router.get('/students', async (req, res) => {
})
router.get('/students/:id', async (req, res) => {
const studentId = req.params.id
const { roles } = req.decodedToken
if (roles && roles.map(r => r.group_code).includes('admin')) {
const { id: studentId } = req.params
const { roles } = req
if (roles && roles.includes('admin')) {
const results = await Student.withId(studentId)
return res.json(results)
return results.error ?
res.status(400).json({ error: 'error finding student' }) :
res.json(results)
}
const uid = req.decodedToken.userId
const student = await Student.withId(studentId)
if (student.error) {
return res.status(400).json({ error: 'error finding student' })
}
const units = await userService.getUnitsFromElementDetails(uid)
const rights = await Promise.all(units.map(async unit => {
@@ -39,9 +46,8 @@ router.get('/students/:id', async (req, res) => {
if (rights.some(right => right !== null)) {
res.json(student).end()
} else {
res.json([]).end()
res.status(400).json({ error: 'error finding student' })
}
})
module.exports = router
@@ -1,6 +1,8 @@
const router = require('express').Router()
const Tags = require('../services/tags')
const TagStudent = require('../services/tagstudent')
const Students = require('../services/students')
const { difference } = require('lodash')
router.get('/tags', async (req, res) => {
try {
@@ -8,40 +10,54 @@ router.get('/tags', async (req, res) => {
res.status(200).json(tags)
} catch (err) {
console.log(err)
res.status(400).json(err)
res.status(500).json(err)
}
})
router.get('/tags/:studytrack', async (req, res) => {
const { studytrack } = req.params
try {
const { studytrack } = req.params
const { rights, roles } = req
if (!rights.includes(studytrack) && !(roles && roles.includes('admin'))) return res.status(403).end()
const tags = await Tags.findTagsByStudytrack(studytrack)
res.status(200).json(tags)
} catch (err) {
console.log(err)
res.status(400).json(err)
res.status(500).json(err)
}
})
router.post('/tags', async (req, res) => {
const { tag } = req.body
try {
const result = await Tags.createNewTag(tag)
res.status(200).json(result)
const { tag } = req.body
const { rights, roles } = req
if (!rights.includes(tag.studytrack) && !(roles && roles.includes('admin'))) return res.status(403).end()
await Tags.createNewTag(tag)
const tags = await Tags.findTagsByStudytrack(tag.studytrack)
res.status(200).json(tags)
} catch (err) {
console.log(err)
res.status(400).json(err.message)
res.status(500).json(err.message)
}
})
router.delete('/tags', async (req, res) => {
const { tag } = req.body
try {
const result = await Tags.deleteTag(tag)
res.status(200).json(result)
const { tag } = req.body
const { rights, roles } = req
if (!rights.includes(tag.studytrack) && !(roles && roles.includes('admin'))) return res.status(403).end()
await Tags.deleteTag(tag)
const t = await Tags.findTagsByStudytrack(tag.studytrack)
res.status(200).json(t)
} catch (err) {
console.log(err)
res.status(400).json(err)
res.status(500).json(err)
}
})
@@ -52,52 +68,94 @@ router.get('/studenttags', async (req, res) => {
res.status(200).json(result)
} catch (err) {
console.log(err)
res.status(400).json(err)
res.status(500).json(err)
}
})
router.get('/studenttags/:studytrack', async (req, res) => {
const { studytrack } = req.params
try {
const { studytrack } = req.params
const { rights, roles } = req
if (!rights.includes(studytrack) && !(roles && roles.includes('admin'))) return res.status(403).end()
const result = await TagStudent.getStudentTagsByStudytrack(studytrack)
res.status(200).json(result)
} catch (err) {
console.log(err)
res.status(400).json(err)
res.status(500).json(err)
}
})
router.get('/studenttags/:studentnumber', async (req, res) => {
const { studentnumber } = req.params
try {
const { studentnumber } = req.params
const result = await TagStudent.getStudentTagsByStudentnumber(studentnumber)
console.log(result)
res.status(200).json(result)
} catch (err) {
console.log(err)
res.status(400).json(err)
res.status(500).json(err)
}
})
router.post('/studenttags/:studentnumber', async (req, res) => {
try {
const { tag, studytrack } = req.body
const { rights, roles } = req
if (!rights.includes(studytrack) && !(roles && roles.includes('admin'))) return res.status(403).end()
await TagStudent.createStudentTag(tag)
const result = await TagStudent.getStudentTagsByStudytrack(studytrack)
res.status(200).json(result)
} catch (err) {
console.log(err)
res.status(500).json(err)
}
})
router.post('/studenttags', async (req, res) => {
const { tag } = req.body
try {
const result = await TagStudent.createStudentTag(tag)
const { tags, studytrack } = req.body
const { rights, roles } = req
if (!rights.includes(studytrack) && !(roles && roles.includes('admin'))) return res.status(403).end()
const existingtags = await Tags.findTagsByStudytrack(studytrack)
const existingTagids = existingtags.map(t => t.tag_id)
const tagids = [...new Set(tags.map(t => t.tag_id))]
if (!tagids.find(t => existingTagids.includes(t))) return res.status(400).json({ error: 'The tag does not exist' })
const studentnumbers = tags.map(t => t.studentnumber)
const students = await Students.filterStudentnumbersByAccessrights(studentnumbers, [studytrack])
const missingStudents = difference(studentnumbers, students)
if (missingStudents.length !== 0) return res.status(400).json({ error: `Could not find the following students from the programme: ${missingStudents.join(', ')}` })
await TagStudent.createMultipleStudentTags(tags)
const result = await TagStudent.getStudentTagsByStudytrack(studytrack)
res.status(200).json(result)
} catch (err) {
console.log(err)
res.status(400).json(err)
res.status(500).json(err)
}
})
router.delete('/studenttags', async (req, res) => {
const { id } = req.body
try {
const result = await TagStudent.deleteStudentTag(id)
const { tag_id, studentnumber, studytrack } = req.body
const { rights, roles } = req
if (!rights.includes(studytrack) && !(roles && roles.includes('admin'))) return res.status(403).end()
const tags = await Tags.findTagsFromStudytrackById(studytrack, [tag_id])
if (tags.length === 0) return res.status(403).json({ error: 'The tag does not exist' })
await TagStudent.deleteStudentTag(studentnumber, tag_id)
const result = await TagStudent.getStudentTagsByStudytrack(studytrack)
res.status(200).json(result)
} catch (err) {
console.log(err)
res.status(400).json(err)
res.status(500).json(err)
}
})
@@ -45,14 +45,15 @@ const mapToProviders = rights => rights.map((r) => {
})
router.get('/stats', async (req, res) => {
const { rights, roles } = req.decodedToken
const { rights, roles } = req
const { providers, semesterStart, semesterEnd } = req.query
if (!providers || !semesterStart) {
return res.status(422).send('Missing required query parameters.')
}
const providerRights = mapToProviders(rights)
if (!(providers.every(p => providerRights.includes(p)) || roles.map(r => r.group_code).includes('admin'))) {
if (!(providers.every(p => providerRights.includes(p)) || roles.includes('admin'))) {
return res.status(403).send('You do not have rights to see this data')
}
const result = await teachers.yearlyStatistics(providers, semesterStart, semesterEnd||semesterStart + 1)
@@ -0,0 +1,129 @@
const router = require('express').Router()
const {
updateOldestStudents,
getStatuses,
updateActiveStudents,
updateAllStudents,
updateAttainments,
updateMetadata,
updateStudentlist,
rescheduleScheduled,
rescheduleFetched,
updateNoStudents
} = require('../services/updaterService')
router.post('/update/oldest', async (req, res) => {
const { amount } = req.body
if (!Number.isInteger(Number(amount))) {
res.status(400).end()
return
}
try {
const response = await updateOldestStudents(amount)
if (response) {
res.status(200).json('Scheduled')
}
} catch (err) {
res.status(500).json(err)
}
})
router.post('/update/all', async (req, res) => {
try {
const response = await updateAllStudents()
if (response) {
res.status(200).json('Scheduled')
}
} catch (err) {
res.status(500).json(err)
}
})
router.post('/update/active', async (req, res) => {
try {
const response = await updateActiveStudents()
if (response) {
res.status(200).json('Scheduled')
}
} catch (err) {
res.status(500).json(err)
}
})
router.post('/update/no_student', async (req, res) => {
try {
const response = await updateNoStudents()
if (response) {
res.status(200).json('Scheduled')
}
} catch (err) {
res.status(500).json(err)
}
})
router.post('/update/attainment', async (req, res) => {
try {
const response = await updateAttainments()
if (response) {
res.status(200).json('Scheduled')
}
} catch (err) {
res.status(500).json(err)
}
})
router.post('/update/meta', async (req, res) => {
try {
const response = await updateMetadata()
if (response) {
res.status(200).json('Scheduled')
}
} catch (err) {
res.status(500).json(err)
}
})
router.post('/update/studentlist', async (req, res) => {
try {
const response = await updateStudentlist()
if (response) {
res.status(200).json('Scheduled')
}
} catch (err) {
res.status(500).json(err)
}
})
router.get('/status', async (req, res) => {
try {
const statuses = await getStatuses()
res.status(200).json(statuses)
} catch (err) {
console.log(err)
res.status(500).json([{ label: 'request status', value: 'request failed' }])
}
})
router.post('/reschedule/scheduled', async (req, res) => {
try {
const response = await rescheduleScheduled()
if (response) {
res.status(200).json('Scheduled')
}
} catch (err) {
res.status(500).json(err)
}
})
router.post('/reschedule/fetched', async (req, res) => {
try {
const response = await rescheduleFetched()
if (response) {
res.status(200).json('Scheduled')
}
} catch (err) {
res.status(500).json(err)
}
})
module.exports = router
@@ -8,11 +8,6 @@ router.get('/', async (req, res) => {
res.json(results)
})
router.get('/enabled', async (req, res) => {
const results = await userService.findAllEnabled()
res.json(results)
})
router.get('/access_groups', async (req, res) => {
const result = await userService.getAccessGroups()
res.json(result)
@@ -38,6 +38,16 @@ const patchThroughput = async (data) => {
return response.data
}
const patchFacultyYearlyStats = async (data) => {
const response = await client.patch('/facultystats', { data })
return response.data
}
const getFacultyYearlyStats = async (data) => {
const response = await client.get('/facultystats', { data })
return response.data
}
module.exports = {
ping,
getProductivity,
@@ -45,5 +55,7 @@ module.exports = {
patchProductivity,
getThroughput,
setThroughput,
patchThroughput
patchThroughput,
patchFacultyYearlyStats,
getFacultyYearlyStats
}
@@ -12,7 +12,6 @@ const isUserBlacklisted = async (userId, tokenCreatedAt) => {
const isBlacklisted = async () => {
const blacklistTimestamp = await redisClient.getAsync(MAKE_REDIS_HASH_KEY(userId))
const status = !!(tokenCreatedAt && blacklistTimestamp && moment(tokenCreatedAt) < moment(blacklistTimestamp))
console.log('BLACKLISTED? ', {isBlacklisted: status, userId, tokenCreatedAt, blacklistTimestamp})
return status
}
const timer = () => new Promise(resolve => setTimeout(() => resolve(true), 5000))
@@ -1,5 +1,8 @@
const { redisClient } = require('../services/redis')
const { Teacher, CourseGroup } = require('../models')
const { Teacher } = require('../models')
const { CourseGroup, TeacherCourseGroup } = require('../models/models_kone')
const { Op } = require('sequelize')
const { flatMap } = require('lodash')
const {
getCurrentAcademicYear,
@@ -26,18 +29,27 @@ const getCurrentAcademicYearSemesterCode = async () => {
return academicYear[0].semestercode
}
const getTeachersForCourseGroup = (courseGroupId) => {
return Teacher.findAll({
attributes: ['name', 'code', 'id'],
const getTeachersForCourseGroup = async (courseGroupId) => {
const courseGroups = await CourseGroup.findAll({
model: CourseGroup,
include: {
model: CourseGroup,
attributes: [],
model: TeacherCourseGroup,
required: true,
where: {
id: courseGroupId
},
},
where: {
id: courseGroupId
},
})
const teacherIds = flatMap(courseGroups, e => e.teacher_course_groups.map(tcg => tcg.teacher_id))
const teachers = await Teacher.findAll({
attributes: ['name', 'code', 'id'],
where: {
id: {
[Op.in]: teacherIds
}
},
})
return teachers
}
const createCourseGroup = (name) => CourseGroup.create({ name })
@@ -141,17 +153,13 @@ const getCoursesByTeachers = async (teacherIds, semesterCode) => {
}
const addTeacher = async (courseGroupId, teacherid) => {
const group = await CourseGroup.findByPk(courseGroupId)
const teacher = await Teacher.findByPk(teacherid)
if (!group || !teacher) return
return await group.addTeacher(teacher)
if (!teacher) return
return TeacherCourseGroup.create({ teacher_id: teacherid, course_group_id: courseGroupId })
}
const removeTeacher = async (courseGroupId, teacherid) => {
const group = await CourseGroup.findByPk(courseGroupId)
const teacher = await Teacher.findByPk(teacherid)
if (!group || !teacher) return
return await group.removeTeacher(teacher)
const removeTeacher = (courseGroupId, teacherid) => {
return TeacherCourseGroup.destroy({ where: { teacher_id: teacherid, course_group_id: courseGroupId } })
}
module.exports = {
@@ -19,7 +19,8 @@ class CourseStatsCounter {
failedMany: {},
improvedPassedGrade: {},
notParticipated: { ...allstudents },
notParticipatedOrFailed: { ...allstudents }
notParticipatedOrFailed: { ...allstudents },
markedToSemester: {}
}
this.stats = {
students: 0,
@@ -67,6 +68,10 @@ class CourseStatsCounter {
this.stats.passingSemesters[semester]++
}
markToSemester(studentnumber) {
this.students.markedToSemester[studentnumber] = true
}
markCredit(studentnumber, grade, passed, failed, improved, semester) {
// studentnumber = `${shajs('sha256').update(process.env.key + studentnumber).digest('hex')}`
this.markAttempt()
@@ -74,10 +79,11 @@ class CourseStatsCounter {
this.markGrade(grade, passed, failed, improved)
this.markToAll(studentnumber)
if (passed) {
this.markPassingGrade(studentnumber)
if (!improved) {
if (!this.students.markedToSemester[studentnumber]) {
this.markPassedSemester(semester)
this.markToSemester(studentnumber)
}
this.markPassingGrade(studentnumber)
} else if (improved) {
this.markImprovedGrade(studentnumber)
} else if (failed) {
@@ -93,11 +99,15 @@ class CourseStatsCounter {
return (this.students.passed[studentnumber] !== undefined)
}
removeFromFailed (studentnumber) {
removeFromFailed(studentnumber) {
delete this.students.failed[studentnumber]
delete this.students.failedMany[studentnumber]
}
removeFromPassed(studentnumber) {
delete this.students.passed[studentnumber]
}
markPassingGrade(studentnumber) {
delete this.students.notParticipatedOrFailed[studentnumber]
this.students.passed[studentnumber] = true
@@ -148,7 +158,7 @@ class CourseStatsCounter {
cumulativeStats['0-SPRING'] = cumulativeStats['0-FALL'] + passingSemesters['0-SPRING']
for (let i = 1; i < 7; i++) {
cumulativeStats[`${i}-FALL`] = cumulativeStats[`${i-1}-SPRING`] + passingSemesters[`${i}-FALL`]
cumulativeStats[`${i}-FALL`] = cumulativeStats[`${i - 1}-SPRING`] + passingSemesters[`${i}-FALL`]
cumulativeStats[`${i}-SPRING`] = cumulativeStats[`${i}-FALL`] + passingSemesters[`${i}-SPRING`]
}
@@ -21,10 +21,11 @@ class CourseYearlyStatsCounter {
this.programmes[code] = { name, students: [] }
}
initGroup(groupcode, name) {
initGroup(groupcode, name, coursecode, yearcode) {
this.groups[groupcode] = {
code: groupcode,
name,
coursecode,
attempts: {
grades: {},
classes: {
@@ -32,7 +33,8 @@ class CourseYearlyStatsCounter {
failed: []
}
},
students: {}
students: {},
yearcode
}
}
@@ -47,8 +49,9 @@ class CourseYearlyStatsCounter {
if (!this.programmes[code]) {
this.initProgramme(code, name)
}
const prog = this.programmes[code]
prog.students.push(studentnumber)
if (!this.programmes[code].students.includes(studentnumber)) {
this.programmes[code].students.push(studentnumber)
}
}
markStudyProgrammes(studentnumber, programmes) {
@@ -88,9 +91,9 @@ class CourseYearlyStatsCounter {
}
}
markCreditToGroup(studentnumber, passed, grade, groupcode, groupname) {
markCreditToGroup(studentnumber, passed, grade, groupcode, groupname, coursecode, yearcode) {
if (!this.groups[groupcode]) {
this.initGroup(groupcode, groupname)
this.initGroup(groupcode, groupname, coursecode, yearcode)
}
this.markCreditToStudents(studentnumber, passed, grade, groupcode)
this.markCreditToAttempts(studentnumber, passed, grade, groupcode)
@@ -114,12 +117,14 @@ class CourseYearlyStatsCounter {
formatStudentStatistics(students) {
const grades = {}
const classes = {}
const studentnumbers = []
Object.entries(students).forEach(([studentnumber, stat]) => {
const { grade, category } = stat
grades[grade] = grades[grade] ? grades[grade].concat(studentnumber) : [studentnumber]
classes[category] = classes[category] ? classes[category].concat(studentnumber) : [studentnumber]
studentnumbers.includes(studentnumber) ? null : studentnumbers.push(studentnumber)
})
return { grades, classes }
return { grades, classes, studentnumbers }
}
formatGroupStatistics() {
@@ -4,8 +4,11 @@ const {
sequelize, Student, Credit,
Course, CourseType, Discipline,
ElementDetails, StudyrightElement,
Studyright, Semester, CourseDuplicates,
Studyright, Semester,
} = require('../models')
const {
sequelizeKone, CourseDuplicates,
} = require('../models/models_kone')
const Op = Sequelize.Op
const { CourseYearlyStatsCounter } = require('../services/course_yearly_stats_counter')
const _ = require('lodash')
@@ -36,7 +39,11 @@ const byName = (name, language) => Course.findAll({
[Op.eq]: name
}
}
}
},
order: [
['latest_instance_date', 'DESC']
],
limit: 1
})
const byNameOrCodeTypeAndDiscipline = (searchTerm, type, discipline, language) => {
@@ -97,7 +104,7 @@ const creditsForCourses = (codes) => Credit.findAll({
attributes: ['studentnumber'],
include: {
model: StudyrightElement,
attributes: ['code'],
attributes: ['code', 'startdate'],
include: [
{
model: ElementDetails,
@@ -193,6 +200,7 @@ const creditsOf = async (codes) => {
fail: credits.filter(Credit.failed).length,
pass: credits.filter(Credit.passed).length,
students: credits.length,
studentnumbers: credits.map(cr => cr.student_studentnumber)
}
}
@@ -235,7 +243,7 @@ const oneYearStats = (instances, year, separate, allInstancesUntilYear) => {
return {
studentsThatPassedThisYear, studentsThatFailedThisYear, allStudentsThatFailedEver,
passedStudentsThatFailedBefore, passedStudentsOnFirstTry, failedStudentsThatFailedBefore,
failedStudentsOnFirstTry, gradeDistribution
failedStudentsOnFirstTry, gradeDistribution, studentnumbers: thisSemester.studentnumbers
}
}
const stats = []
@@ -326,8 +334,7 @@ const yearlyStatsOf = async (code, year, separate, language) => {
return b
}, resultProgrammes)
const alternatives = await getDuplicateCodes(code)
const codes = alternatives ? alternatives : [code]
const codes = await alternativeCodes(code)
const allInstances = await creditsOf(codes)
const yearInst = allInstances
.filter(inst => moment(new Date(inst.date)).isBetween(year.start + '-09-01', year.end + '-08-01'))
@@ -409,7 +416,7 @@ const deleteDuplicateCode = async (code) => {
coursecode: code
}
})
await sequelize.query(
await sequelizeKone.query(
`DELETE FROM course_duplicates
WHERE groupid in ( SELECT groupid FROM course_duplicates
group by groupid
@@ -421,12 +428,17 @@ const deleteDuplicateCode = async (code) => {
}
}
const getDuplicateCodesWithCourses = () => {
return CourseDuplicates.findAll({
include: {
model: Course,
const getDuplicateCodesWithCourses = async () => {
const courseDuplicates = await CourseDuplicates.findAll()
const courses = await Course.findAll({
where: {
code: {
[Op.in]: courseDuplicates.map(e => e.coursecode)
}
}
})
const codeToCourse = courses.reduce((acc, c) => { acc[c.code] = c; return acc }, {})
return courseDuplicates.map(cd => ({ ...cd.get(), course: codeToCourse[cd.coursecode] }))
}
const getDuplicatesToIdMap = () => {
@@ -463,20 +475,19 @@ const getMainCodeToDuplicates = async () => {
)[0]
acc[main.code] = {
maincourse: { code: main.code, name: main.name },
duplicates: courses.map( c => ({ code: c.code, name: c.name }))
duplicates: courses.map(c => ({ code: c.code, name: c.name }))
}
return acc
}, {})
return maincodeToDuplicates
}
const getCodeToMainCodeMap = async () => {
const getCodeToMainCourseMap = async () => {
try {
const maincodeToDuplicates = await getMainCodeToDuplicates()
const codeToMainCode = Object.values(maincodeToDuplicates).reduce((acc, d) => {
const maincode = d.maincourse.code
d.duplicates.forEach((c) => {
acc[c.code] = maincode
acc[c.code] = d.maincourse
})
return acc
}, {})
@@ -487,37 +498,19 @@ const getCodeToMainCodeMap = async () => {
return {}
}
const getMainCodesMap = async () => {
return await getCodeToMainCodeMap()
}
const getMaincodeToDuplicateCodesMap = async () => {
try {
const codeToMainCodeMap = await getCodeToMainCodeMap()
const codes = Object.keys(codeToMainCodeMap)
const mainCodeToCoursesMap = codes.reduce((acc, code) => {
const maincode = codeToMainCodeMap[code]
const duplicates = acc[maincode] || []
duplicates.push(code)
acc[maincode] = duplicates
return acc
}, {})
return mainCodeToCoursesMap
} catch (e) {
console.error(e)
}
return {}
const getMainCodeToDuplicatesAndCodeToMainCode = async () => {
return [await getMainCodeToDuplicates(), await getCodeToMainCourseMap()]
}
const getMainCourseToCourseMap = async (/*programme*/) => {
try {
const codeToMainCodeMap = await getCodeToMainCodeMap()
const codeToMainCodeMap = await getCodeToMainCourseMap()
const courses = await byCodes(Object.keys(codeToMainCodeMap))
const mainCodeToCoursesMap = courses.reduce((acc, course) => {
const maincode = codeToMainCodeMap[course.code]
const duplicates = acc[maincode] || []
const maincourse = codeToMainCodeMap[course.code]
const duplicates = acc[maincourse.code] || []
duplicates.push(course)
acc[maincode] = duplicates
acc[maincourse.code] = duplicates
return acc
}, {})
return mainCodeToCoursesMap
@@ -528,9 +521,10 @@ const getMainCourseToCourseMap = async (/*programme*/) => {
}
const getDuplicateCodes = async (code) => {
const maincodeToDuplicatesMap = await getMaincodeToDuplicateCodesMap()
const duplicates = maincodeToDuplicatesMap[code]
return duplicates
const [mainCodeToDuplicates, codeToMainCourseMap] = await getMainCodeToDuplicatesAndCodeToMainCode()
const maincourse = codeToMainCourseMap[code]
if (!maincourse) return null
return mainCodeToDuplicates[maincourse.code].duplicates.map(e => e.code)
}
const setDuplicateCode = async (code1, code2) => {
@@ -541,12 +535,12 @@ const setDuplicateCode = async (code1, code2) => {
if (course1 && course2) {
const all = await getDuplicatesToIdMap()
// make sure both dont have a group
if ([all[code1], all[code2]].filter(e=>e).length <= 1) {
if ([all[code1], all[code2]].filter(e => e).length <= 1) {
let groupid = all[code1] || all[code2]
if (!groupid) {
// neither has a group, make one
groupid = Math.max(0, ...Object.values(all).filter(e=>e))
groupid = groupid && !isNaN(groupid) ? groupid+1 : 1
groupid = Math.max(0, ...Object.values(all).filter(e => e))
groupid = groupid && !isNaN(groupid) ? groupid + 1 : 1
}
await CourseDuplicates.bulkCreate([
{ groupid, coursecode: code1 },
@@ -572,13 +566,14 @@ const alternativeCodes = async code => {
return alternatives ? alternatives : [code]
}
const formatStudyrightElement = ({ code, element_detail }) => ({
const formatStudyrightElement = ({ code, element_detail, startdate }) => ({
code,
name: element_detail.name
name: element_detail.name,
startdate
})
const parseCredit = credit => {
const { student, semester, grade } = credit
const { student, semester, grade, course_code } = credit
const { studentnumber, studyright_elements: elements } = student
const { yearcode, yearname, semestercode, name: semestername } = semester
return {
@@ -587,6 +582,7 @@ const parseCredit = credit => {
yearname,
semestercode,
semestername,
coursecode: course_code,
grade,
passed: !Credit.failed(credit) || Credit.passed(credit) || Credit.improved(credit),
studentnumber,
@@ -594,7 +590,7 @@ const parseCredit = credit => {
}
}
const yearlyStatsOfNew = async (coursecode, separate, startyearcode, endyearcode) => {
const yearlyStatsOfNew = async (coursecode, separate) => {
const codes = await alternativeCodes(coursecode)
const [credits, course] = await Promise.all([creditsForCourses(codes), Course.findByPk(coursecode)])
const counter = new CourseYearlyStatsCounter()
@@ -602,25 +598,22 @@ const yearlyStatsOfNew = async (coursecode, separate, startyearcode, endyearcode
const {
studentnumber, grade, passed,
semestercode, semestername,
yearcode, yearname, programmes
yearcode, yearname, programmes,
coursecode
} = parseCredit(credit)
if (startyearcode <= yearcode && yearcode <= endyearcode) {
const groupcode = separate ? semestercode : yearcode
const groupname = separate ? semestername : yearname
const unknownProgramme = [{
code: 'OTHER',
name: {
en: 'Other',
fi: 'Muu',
sv: 'Andra'
}
}]
counter.markStudyProgrammes(studentnumber, programmes.length === 0 ? unknownProgramme : programmes)
counter.markCreditToGroup(studentnumber, passed, grade, groupcode, groupname)
} else {
counter.markCreditToHistory(studentnumber, passed)
}
const groupcode = separate ? semestercode : yearcode
const groupname = separate ? semestername : yearname
const unknownProgramme = [{
code: 'OTHER',
name: {
en: 'Other',
fi: 'Muu',
sv: 'Andra'
}
}]
counter.markStudyProgrammes(studentnumber, programmes.length === 0 ? unknownProgramme : programmes)
counter.markCreditToGroup(studentnumber, passed, grade, groupcode, groupname, coursecode, yearcode)
counter.markCreditToHistory(studentnumber, passed)
}
const statistics = counter.getFinalStatistics()
return {
@@ -631,10 +624,9 @@ const yearlyStatsOfNew = async (coursecode, separate, startyearcode, endyearcode
}
}
const courseYearlyStats = async (coursecodes, separate, startyearcode, endyearcode) => {
const courseYearlyStats = async (coursecodes, separate) => {
const stats = await Promise.all(coursecodes
.map(code => yearlyStatsOfNew(code, separate, startyearcode, endyearcode || startyearcode)))
.map(code => yearlyStatsOfNew(code, separate)))
return stats
}
@@ -662,7 +654,7 @@ const nameLikeTerm = (name) => {
const codeLikeTerm = (code) => !code ? undefined : {
code: {
[Op.iLike]: `${code.trim()}%`
[Op.iLike]: `%${code.trim()}%`
}
}
@@ -701,12 +693,13 @@ module.exports = {
findDuplicates,
setDuplicateCode,
deleteDuplicateCode,
getMainCodesMap,
getCodeToMainCourseMap,
getMainCourseToCourseMap,
getAllCourseTypes,
getAllDisciplines,
yearlyStatsOfNew,
courseYearlyStats,
byNameAndOrCodeLike,
byCodes
byCodes,
getMainCodeToDuplicatesAndCodeToMainCode
}
@@ -250,12 +250,7 @@ const getTransfersFromData = (data, studentnumber) => {
const studytracks = data.elements.filter(element => element.element_id === 20)
const sorted = _.sortBy(studytracks, 'end_date')
let transfers = []
let i = 0
while (i < sorted.length) {
if (i === 0) {
i++
continue
}
for (let i = 1; i < sorted.length; ++i) {
let target = sorted[i].code
let source = sorted[i - 1].code
let transferdate = sorted[i - 1].end_date
@@ -266,7 +261,6 @@ const getTransfersFromData = (data, studentnumber) => {
transferdate,
studentnumber,
studyrightid: `${data.studyright_id}`})
i++
}
return(transfers)
}
@@ -5,10 +5,10 @@ const https = require('https')
const fs = require('fs')
const base_url = OODI_ADDR
const agent = KEY_PATH && CERT_PATH ?
const agent = KEY_PATH && CERT_PATH ?
new https.Agent({
cert: fs.readFileSync(process.env.CERT_PATH, 'utf8'),
key: fs.readFileSync(process.env.KEY_PATH, 'utf8'),
key: fs.readFileSync(process.env.KEY_PATH, 'utf8'),
}) :
new https.Agent({
rejectUnauthorized: false
@@ -48,9 +48,10 @@ if (process.env.NODE_ENV === 'dev') {
username: 'tktl',
password: process.env.OODI_PW
}
axios.defaults.params = {
token: process.env.TOKEN
}
instance.interceptors.request.use((config) => {
config.params = {token: process.env.TOKEN}
return config
})
}
@@ -1,7 +1,13 @@
const { ElementDetails } = require('../models/index')
const { Op } = require('sequelize')
const byId = id => ElementDetails.findByPk(id)
const byId = id => ElementDetails.findByPk(id)
const byType = type => ElementDetails.findAll({
where: {
type
}
})
const byCodes = codes => ElementDetails.findAll({
where: {
@@ -11,4 +17,4 @@ const byCodes = codes => ElementDetails.findAll({
}
})
module.exports = { byId, byCodes }
module.exports = { byId, byType, byCodes }
@@ -0,0 +1,72 @@
const axios = require('axios')
const moment = require('moment')
const AsyncLock = require('async-lock')
const { USERSERVICE_URL } = require('../conf-backend')
const { Credit, StudyrightElement } = require('../models')
const client = axios.create({ baseURL: USERSERVICE_URL, headers: { 'secret': process.env.USERSERVICE_SECRET } })
const calculateFacultyYearlyStats = async () => {
const { data: facultyProgrammes } = await client.get('/faculty_programmes')
const res = {}
const lock = new AsyncLock()
let amountDone = 0
await Promise.all(facultyProgrammes.map(({ faculty_code, programme_code }) => (
new Promise(async (facultyRes) => {
if (!res[faculty_code]) res[faculty_code] = {}
if (!res[faculty_code][programme_code]) res[faculty_code][programme_code] = {}
const facultyStudents = await StudyrightElement.findAll({
where: {
code: programme_code
},
attributes: ['studentnumber']
})
await Promise.all(facultyStudents.map((student) => (
new Promise(async (studentRes) => {
const filteredStudentCredits = await Credit.findAll({
where: {
student_studentnumber: student.studentnumber,
credittypecode: [4, 10],
isStudyModule: false
}
})
filteredStudentCredits.forEach((c) => {
const attainmentYear = moment(c.attainment_date).year()
if (!res[faculty_code][attainmentYear]) {
lock.acquire(faculty_code, (done) => {
if (!res[faculty_code][programme_code][attainmentYear]) {
const facultyYearStats = {}
facultyYearStats.studentCredits = 0
facultyYearStats.coursesPassed = 0
facultyYearStats.coursesFailed = 0
res[faculty_code][programme_code][attainmentYear] = facultyYearStats
}
done()
})
}
const facultyYearStats = res[faculty_code][programme_code][attainmentYear]
if (c.credittypecode === 4) {
facultyYearStats.studentCredits += c.credits
facultyYearStats.coursesPassed += 1
} else {
facultyYearStats.coursesFailed += 1
}
})
studentRes()
})
)))
amountDone += 1
console.log(`Faculty programmes done ${amountDone}/${facultyProgrammes.length}`)
facultyRes()
})
)))
return res
}
module.exports = {
calculateFacultyYearlyStats
}
@@ -1,5 +1,5 @@
const Sequelize = require('sequelize')
const { Filters } = require('../models')
const { Filters } = require('../models/models_kone')
const Op = Sequelize.Op
@@ -66,7 +66,7 @@ const feedback = (content, user, email, full_name) => {
return ({
to: 'Toska <grp-toska@helsinki.fi>',
replyTo: email,
subject: `New message from Oodikone feedback`,
subject: 'New message from Oodikone feedback',
text: `New message from user ${user}`,
html: `${content}
<p>sent by ${full_name}, userid: ${user}, email: ${email}</p>
@@ -1,10 +1,7 @@
const Sequelize = require('sequelize')
const _ = require('lodash')
const { MandatoryCourseLabels } = require('../models')
const { MandatoryCourseLabels, sequelizeKone } = require('../models/models_kone')
const { Op } = Sequelize
const {
sequelize
} = require('../models/index')
const create = async (studyprogramme_id, { label }) => {
const labels = await labelsByStudyprogramme(studyprogramme_id)
@@ -23,7 +20,7 @@ const move = async (studyprogramme_id, { id }, direction) => {
if (indexToSwap < 0 || indexToSwap >= orderedlabels.length) return null;
[orderedlabels[indexToMove], orderedlabels[indexToSwap]] = [orderedlabels[indexToSwap], orderedlabels[indexToMove]]
const newOrder = orderedlabels.map((e, index) => ({ ...e, orderNumber: index }))
await sequelize.transaction(async transaction => {
await sequelizeKone.transaction(async transaction => {
for (let e of newOrder) {
await MandatoryCourseLabels.update(
{orderNumber: e.orderNumber}, { where: { studyprogramme_id, id: e.id }, transaction }
@@ -1,15 +1,12 @@
const Sequelize = require('sequelize')
const { Course, MandatoryCourse, MandatoryCourseLabels } = require('../models')
const { Course } = require('../models')
const { MandatoryCourse, MandatoryCourseLabels } = require('../models/models_kone')
const { Op } = Sequelize
const byStudyprogramme = (studyProgrammeId) => {
const courses = MandatoryCourse.findAll({
const byStudyprogramme = async (studyProgrammeId) => {
const mandatoryCourses = await MandatoryCourse.findAll({
attributes: ['course_code'],
include: [
{
model: Course,
attributes: ['name'],
},
{
model: MandatoryCourseLabels,
attributes: ['id', 'label', 'orderNumber'],
@@ -22,10 +19,20 @@ const byStudyprogramme = (studyProgrammeId) => {
}
})
return courses.map(course => ({
name: course.course.name,
code: course.course_code,
label: course.mandatory_course_label
const courses = await Course.findAll({
model: Course,
where: {
code: {
[Op.in]: mandatoryCourses.map(c => c.course_code)
}
}
})
const courseCodeToCourse = courses.reduce((acc, c) => { acc[c.code] = c; return acc }, {})
return mandatoryCourses.map(mc => ({
name: courseCodeToCourse[mc.course_code].name,
code: mc.course_code,
label: mc.mandatory_course_label
}))
}
@@ -36,14 +43,10 @@ const create = (studyProgrammeId, code) => {
})
}
const find = (studyProgrammeId, code) => {
return MandatoryCourse.findOne({
const find = async (studyProgrammeId, code) => {
const mandatoryCourse = await MandatoryCourse.findOne({
attributes: ['course_code', 'label'],
include: [
{
model: Course,
attributes: ['name'],
},
{
model: MandatoryCourseLabels,
attributes: ['id', 'label', 'orderNumber'],
@@ -58,6 +61,16 @@ const find = (studyProgrammeId, code) => {
}
}
})
if (!mandatoryCourse) return null
const course = await Course.findOne({
where: {
code: mandatoryCourse.course_code
}
})
if (!course) return null
return { ...mandatoryCourse.get(), course: course.get() }
}
const remove = (studyProgrammeId, code) => {
@@ -1,12 +1,14 @@
const { Op } = require('sequelize')
const moment = require('moment')
const { orderBy } = require('lodash')
const {
Student, Credit, Course, sequelize, Studyright, StudyrightExtent, ElementDetails,
Discipline, CourseType, SemesterEnrollment, Semester, Transfers, StudyrightElement,
Tag, TagStudent
Discipline, CourseType, SemesterEnrollment, Semester, Transfers, StudyrightElement
} = require('../models')
const { getMainCodesMap, byName } = require('./courses')
const {
Tag, TagStudent
} = require('../models/models_kone')
const { getCodeToMainCourseMap } = require('./courses')
const { CourseStatsCounter } = require('./course_stats_counter')
const { getPassingSemester, semesterEnd, semesterStart } = require('../util/semester')
@@ -25,7 +27,7 @@ const formatStudentForPopulationStatistics = ({
firstnames, lastname, studentnumber, dateofuniversityenrollment, creditcount,
matriculationexamination, credits, abbreviatedname, email, studyrights,
semester_enrollments, transfers, updatedAt, createdAt, gender_code,
gender_fi, gender_sv, gender_en, tag_students
gender_fi, gender_sv, gender_en, tags
}, startDate, endDate) => {
const toCourse = ({ grade, attainment_date, credits, course, credittypecode, isStudyModule }) => {
@@ -99,7 +101,7 @@ const formatStudentForPopulationStatistics = ({
email,
semesterenrollments,
updatedAt: updatedAt || createdAt,
tags: tag_students || [],
tags: tags || [],
studyrightStart: startDate,
starting: moment(started).isBetween(startDate, endDate, null, '[]')
}
@@ -107,7 +109,8 @@ const formatStudentForPopulationStatistics = ({
const dateMonthsFromNow = (date, months) => moment(date).add(months, 'months').format('YYYY-MM-DD')
const getStudentsIncludeCoursesBetween = async (studentnumbers, startDate, endDate, studyright) => {
const getStudentsIncludeCoursesBetween = async (studentnumbers, startDate, endDate, studyright, tag) => {
const creditsOfStudentOther = {
student_studentnumber: {
[Op.in]: studentnumbers
@@ -138,9 +141,9 @@ const getStudentsIncludeCoursesBetween = async (studentnumbers, startDate, endDa
const creditsOfStudent = ['320001', 'MH30_001'].includes(studyright[0]) ?
creditsOfStudentLaakis : creditsOfStudentOther
const students = await Student.findAll({
attributes: ['firstnames', 'lastname', 'studentnumber',
attributes: ['firstnames', 'lastname', 'studentnumber', 'home_country_en',
'dateofuniversityenrollment', 'creditcount', 'matriculationexamination',
'abbreviatedname', 'email', 'updatedAt', 'gender_code', 'gender_fi', 'gender_sv', 'gender_en'],
include: [
@@ -213,17 +216,21 @@ const getStudentsIncludeCoursesBetween = async (studentnumbers, startDate, endDa
}
}
},
{
model: TagStudent,
attributes: ['id'],
include: [
{
model: Tag,
attributes: ['tag_id','tagname']
}
],
],
where: {
studentnumber: {
[Op.in]: studentnumbers
}
},
})
const studentTags = await TagStudent.findAll({
attributes: ['tag_id', 'studentnumber'],
include: [
{
model: Tag,
attributes: ['tag_id', 'tagname'],
}
],
where: {
studentnumber: {
@@ -231,6 +238,17 @@ const getStudentsIncludeCoursesBetween = async (studentnumbers, startDate, endDa
}
}
})
const studentNumberToTags = studentTags.reduce((acc, t) => {
acc[t.studentnumber] = acc[t.studentnumber] || []
acc[t.studentnumber].push(t)
return acc
}, {})
students.forEach(student => {
student.tags = studentNumberToTags[student.studentnumber] || []
})
if (tag) return students.filter(student => student.tags.some(t => t.tag_id === tag))
return students
}
@@ -243,7 +261,7 @@ const count = (column, count, distinct = false) => {
)
}
const studentnumbersWithAllStudyrightElements = async (studyRights, startDate, endDate, exchangeStudents, cancelledStudents, nondegreeStudents) => { // eslint-disable-line
const studentnumbersWithAllStudyrightElements = async (studyRights, startDate, endDate, exchangeStudents, cancelledStudents, nondegreeStudents, tag) => { // eslint-disable-line
const filteredExtents = []
let studyrightWhere = {
extentcode: {
@@ -260,6 +278,21 @@ const studentnumbersWithAllStudyrightElements = async (studyRights, startDate, e
studyrightWhere.canceldate = null
}
let studentWhere = {}
if (tag) {
const taggedStudentnumbers = await TagStudent.findAll({
attributes: ['studentnumber'],
where: {
tag_id: tag
}
})
studentWhere.where = {
student_studentnumber: {
[Op.in]: taggedStudentnumbers.map(sn => sn.studentnumber)
}
}
}
const students = await Studyright.findAll({
attributes: ['student_studentnumber'],
include: {
@@ -293,21 +326,22 @@ const studentnumbersWithAllStudyrightElements = async (studyRights, startDate, e
}
],
...studyrightWhere
},
...studentWhere,
having: count('studyright_elements.code', studyRights.length, true),
})
return [...new Set(students.map(s => s.student_studentnumber))]
}
const parseQueryParams = query => {
const { semesters, studentStatuses, year, studyRights, months } = query
const { semesters, studentStatuses, studyRights, months, endYear, startYear, tag } = query
const startDate = semesters.includes('FALL') ?
`${year}-${semesterStart[semesters.find(s => s === 'FALL')]}` :
`${moment(year, 'YYYY').add(1, 'years').format('YYYY')}-${semesterStart[semesters.find(s => s === 'SPRING')]}`
`${startYear}-${semesterStart[semesters.find(s => s === 'FALL')]}` :
`${moment(startYear, 'YYYY').add(1, 'years').format('YYYY')}-${semesterStart[semesters.find(s => s === 'SPRING')]}`
const endDate = semesters.includes('SPRING') ?
`${moment(year, 'YYYY').add(1, 'years').format('YYYY')}-${semesterEnd[semesters.find(s => s === 'SPRING')]}` :
`${year}-${semesterEnd[semesters.find(s => s === 'FALL')]}`
`${moment(endYear, 'YYYY').add(1, 'years').format('YYYY')}-${semesterEnd[semesters.find(s => s === 'SPRING')]}` :
`${endYear}-${semesterEnd[semesters.find(s => s === 'FALL')]}`
const exchangeStudents = studentStatuses && studentStatuses.includes('EXCHANGE')
const cancelledStudents = studentStatuses && studentStatuses.includes('CANCELLED')
const nondegreeStudents = studentStatuses && studentStatuses.includes('NONDEGREE')
@@ -318,7 +352,8 @@ const parseQueryParams = query => {
studyRights: Array.isArray(studyRights) ? studyRights : Object.values(studyRights),
months,
startDate,
endDate
endDate,
tag
}
}
@@ -365,32 +400,28 @@ const formatStudentsForApi = async (students, startDate, endDate, { studyRights
stats.students.push(formatStudentForPopulationStatistics(student, startDate, endDate))
return stats
}, {
students: [],
extents: {},
semesters: {},
transfers: {
targets: {},
sources: {}
},
studyrights: {
degrees: [],
programmes: []
}
})
students: [],
extents: {},
semesters: {},
transfers: {
targets: {},
sources: {}
},
studyrights: {
degrees: [],
programmes: []
}
})
const [momentstart, momentend] = [moment(startDate), moment(endDate)]
const transferredStudyright = (s) => {
const studyright = s.studyrights.find(s => s.studyrightElements
.map(d => d.element_detail.code)
.includes(studyRights.programme))
if (studyright) {
s.transferredStudyright = moment(startDate).isAfter(moment(studyright.startdate))
if (s.transferredStudyright) {
const previousRights = studyright.studyrightElements
.filter(e => e.element_detail.type === 20 && e.element_detail.code !== studyRights.programme)
s.previousRights = previousRights
}
const transferred_from = s.transfers.find(
t => t.target.code === studyRights.programme &&
moment(t.transferdate).isBetween(momentstart, momentend)
)
if (transferred_from) {
s.transferredStudyright = true
s.transferSource = transferred_from.source
}
return s
}
@@ -404,44 +435,60 @@ const formatStudentsForApi = async (students, startDate, endDate, { studyRights
}
}
const optimizedStatisticsOf = async (query) => {
if (!query.semesters.map(semester => semester === 'FALL' || semester === 'SPRING').every(e => e === true)) {
const formatQueryParamArrays = (query, params) => {
let res = { ...query }
params.forEach(p => {
if (!res[p]) return
res[p] = Array.isArray(res[p]) ? res[p] : [res[p]]
})
return res
}
const optimizedStatisticsOf = async (query, studentnumberlist) => {
const formattedQueryParams = formatQueryParamArrays(query, ['semesters', 'studentStatuses'])
if (!formattedQueryParams.semesters.map(semester => semester === 'FALL' || semester === 'SPRING').every(e => e === true)) {
return { error: 'Semester should be either SPRING OR FALL' }
}
if (query.studentStatuses &&
!query.studentStatuses.map(
if (formattedQueryParams.studentStatuses &&
!formattedQueryParams.studentStatuses.map(
status => status === 'CANCELLED' || status === 'EXCHANGE' || status === 'NONDEGREE'
).every(e => e === true)
) {
return { error: 'Student status should be either CANCELLED or EXCHANGE or NONDEGREE' }
}
const {
studyRights, startDate, endDate, months, exchangeStudents, cancelledStudents, nondegreeStudents
} = parseQueryParams(query)
studyRights, startDate, months, endDate, exchangeStudents, cancelledStudents, nondegreeStudents
} = parseQueryParams(formattedQueryParams)
const studentnumbers =
const studentnumbers = studentnumberlist ?
studentnumberlist :
await studentnumbersWithAllStudyrightElements(
studyRights, startDate, endDate, exchangeStudents, cancelledStudents, nondegreeStudents
)
const students =
await getStudentsIncludeCoursesBetween(studentnumbers, startDate, dateMonthsFromNow(startDate, months), studyRights)
const students = await getStudentsIncludeCoursesBetween(
studentnumbers,
startDate,
dateMonthsFromNow(startDate, months),
studyRights,
formattedQueryParams.tag
)
const formattedStudents = await formatStudentsForApi(students, startDate, endDate, query)
const formattedStudents = await formatStudentsForApi(students, startDate, endDate, formattedQueryParams)
return formattedStudents
}
const unifyOpenUniversity = (code) => {
if (code[0] === 'A') {
return code.substring(code[1] === 'Y' ? 2 : 1)
}
return code
const regexresult = code.match(/^AY?(.+?)(?:en|fi|sv)?$/)
if (!regexresult) return code
return regexresult[1]
}
const getUnifiedCode = (code, codeduplicates) => {
const formattedcode = unifyOpenUniversity(code)
const unifiedcode = codeduplicates[formattedcode]
return !unifiedcode ? formattedcode : unifiedcode
const getMainCourse = (course, codeduplicates) => {
const formattedcode = unifyOpenUniversity(course.code)
const maincourse = codeduplicates[formattedcode]
return maincourse || course
}
const findCourses = (studentnumbers, beforeDate) => {
@@ -459,8 +506,7 @@ const findCourses = (studentnumbers, beforeDate) => {
attainment_date: {
[Op.lt]: beforeDate
}
},
order: 'attainment_date'
}
},
{
model: Discipline
@@ -486,53 +532,71 @@ const parseCreditInfo = credit => ({
date: credit.attainment_date
})
const bottlenecksOf = async (query) => {
if (!query.semesters.map(semester => semester === 'FALL' || semester === 'SPRING').every(e => e === true)) {
return { error: 'Semester should be either SPRING OR FALL' }
const bottlenecksOf = async (query, studentnumberlist) => {
const isValidRequest = async (query, params) => {
const { studyRights, startDate, endDate, exchangeStudents, cancelledStudents, nondegreeStudents } = params
if (!query.semesters.every(semester => semester === 'FALL' || semester === 'SPRING')) {
return { error: 'Semester should be either SPRING OR FALL' }
}
if (query.studentStatuses &&
!query.studentStatuses.every(
status => status === 'CANCELLED' || status === 'EXCHANGE' || status === 'NONDEGREE'
)) {
return { error: 'Student status should be either CANCELLED or EXCHANGE or NONDEGREE' }
}
if (query.selectedStudents) {
const allStudents =
await studentnumbersWithAllStudyrightElements(
studyRights, startDate, endDate, exchangeStudents, cancelledStudents, nondegreeStudents, query.tag
)
const disallowedRequest =
checkThatSelectedStudentsAreUnderRequestedStudyright(query.selectedStudents, allStudents)
if (disallowedRequest) return { error: 'Trying to request unauthorized students data' }
}
return null
}
if (query.studentStatuses &&
!query.studentStatuses.map(
status => status === 'CANCELLED' || status === 'EXCHANGE' || status === 'NONDEGREE'
).every(e => e === true)) {
return { error: 'Student status should be either CANCELLED or EXCHANGE or NONDEGREE' }
const getStudentsAndCourses = async (selectedStudents, studentnumberlist) => {
if (!studentnumberlist) {
const { months, studyRights, startDate, endDate, exchangeStudents, cancelledStudents, nondegreeStudents, tag } = params
const studentnumbers = selectedStudents ||
await studentnumbersWithAllStudyrightElements(studyRights, startDate, endDate, exchangeStudents, cancelledStudents, nondegreeStudents, tag)
const allstudents = studentnumbers.reduce((numbers, num) => ({ ...numbers, [num]: true }), {})
const courses = await findCourses(studentnumbers, dateMonthsFromNow(startDate, months))
return [allstudents, courses]
} else {
const allstudents = studentnumberlist
const courses = await findCourses(allstudents, new Date())
return [allstudents, courses]
}
}
const { studyRights, startDate, endDate, months, exchangeStudents, cancelledStudents } = parseQueryParams(query)
if (query.selectedStudents) {
const allStudents =
await studentnumbersWithAllStudyrightElements(
studyRights, startDate, endDate, exchangeStudents, cancelledStudents
const params = parseQueryParams(query)
const [[allstudents, courses], codeToMainCourse, error] = await Promise.all(
[
getStudentsAndCourses(query.selectedStudents, studentnumberlist),
getCodeToMainCourseMap(),
isValidRequest(
query,
params
)
const disallowedRequest =
checkThatSelectedStudentsAreUnderRequestedStudyright(query.selectedStudents, allStudents)
if (disallowedRequest) return { error: 'Trying to request unauthorized students data' }
}
]
)
if (error) return error
const bottlenecks = {
disciplines: {},
coursetypes: {}
}
const codeduplicates = await getMainCodesMap()
const stats = {}
const studentnumbers = query.selectedStudents ||
await studentnumbersWithAllStudyrightElements(studyRights, startDate, endDate, exchangeStudents, cancelledStudents)
const allstudents = studentnumbers.reduce((numbers, num) => ({ ...numbers, [num]: true }), {})
const courses = await findCourses(studentnumbers, dateMonthsFromNow(startDate, months))
const allcoursestatistics = await courses.reduce(async (coursestatistics, course) => {
const stats = await coursestatistics
let { code, name, disciplines, course_type } = course
if (name.fi && name.fi.includes('Avoin yo:')) {
const courses = await byName(name.fi.split(': ')[1], 'fi')
const theOne = courses.length > 0 ? orderBy(courses, ['date'], ['desc'])[0] : { name, code }
code = theOne.code
name = theOne.name
const startYear = parseInt(query.endYear, 10)
courses.forEach(course => {
let { disciplines, course_type } = course
const maincourse = getMainCourse(course, codeToMainCourse)
if (!stats[maincourse.code]) {
stats[maincourse.code] = new CourseStatsCounter(maincourse.code, maincourse.name, allstudents)
}
const unifiedcode = getUnifiedCode(code, codeduplicates)
const coursestats = stats[unifiedcode] || new CourseStatsCounter(unifiedcode, name, allstudents)
const coursestats = stats[maincourse.code]
coursestats.addCourseType(course_type.coursetypecode, course_type.name)
bottlenecks.coursetypes[course_type.coursetypecode] = course_type.name
@@ -543,18 +607,13 @@ const bottlenecksOf = async (query) => {
course.credits.forEach(credit => {
const { studentnumber, passingGrade, improvedGrade, failingGrade, grade, date } = parseCreditInfo(credit)
const semester = getPassingSemester(parseInt(query.year, 10), date)
const semester = getPassingSemester(startYear, date)
coursestats.markCredit(studentnumber, grade, passingGrade, failingGrade, improvedGrade, semester)
})
stats[unifiedcode] = coursestats
return stats
}, Promise.resolve({}))
bottlenecks.coursestatistics = Object.values(allcoursestatistics)
stats[maincourse.code] = coursestats
})
bottlenecks.coursestatistics = Object.values(stats)
.map(coursestatistics => coursestatistics.getFinalStats())
return bottlenecks
}
@@ -1,15 +1,8 @@
const sequelize = require('sequelize')
const { Semester } = require('../models/index')
const { Op } = sequelize
const getSemestersAndYears = async before => {
const semesters = await Semester.findAll({
where: {
startdate: {
[Op.lt]: before
}
}
})
const getSemestersAndYears = async () => {
const semesters = await Semester.findAll({})
const result = semesters.reduce((acc, semester) => {
const { semestercode, name, yearcode, yearname } = semester
const semesters = { ...acc.semesters, [semestercode]: { semestercode, name, yearcode }}
@@ -1,4 +1,5 @@
const Sequelize = require('sequelize')
const { sequelize } = require('../database/connection')
const moment = require('moment')
const { Student, Credit, Course, Studyright, StudyrightElement, ElementDetails } = require('../models')
const Op = Sequelize.Op
@@ -41,6 +42,23 @@ const byId = async (id) => Student.findByPk(id, {
]
})
const findByCourseAndSemesters = async (coursecodes, yearcode) =>
sequelize.query(`
SELECT
studentnumber, credit.course_code, attainment_date
FROM student
INNER JOIN credit ON
student.studentnumber=credit.student_studentnumber
WHERE
course_code IN (:coursecodes) AND
attainment_date
BETWEEN
(select startdate FROM semesters where yearcode=:yearcode ORDER BY semestercode LIMIT 1) AND
(select enddate FROM semesters where yearcode=:yearcode ORDER BY semestercode DESC LIMIT 1);
`,
{ replacements: { coursecodes, yearcode }, type: sequelize.QueryTypes.SELECT })
.map(st => st.studentnumber)
const byAbreviatedNameOrStudentNumber = (searchTerm) => {
return Student.findAll({
where: {
@@ -280,10 +298,36 @@ const bySearchTermAndElementsNew = async (searchterm, codes) => {
return matches.map(formatStudent)
}
const filterStudentnumbersByAccessrights = async (studentnumbers, codes) => {
const students = await Student.findAll({
include: {
model: StudyrightElement,
required: true,
where: {
code: {
[Op.in]: codes
}
}
},
where: {
studentnumber: {
[Op.in]: studentnumbers
}
}
})
return students.map(student => student.studentnumber)
}
const NEW_SEARCH = true
const bySearchTerm = NEW_SEARCH ? bySearchTermNew : bySearchTermOld
const bySearchTermAndElements = NEW_SEARCH ? bySearchTermAndElementsNew : bySearchTermAndElementsOld
module.exports = {
withId, bySearchTerm, createStudent, updateStudent, bySearchTermAndElements
withId,
bySearchTerm,
createStudent,
updateStudent,
bySearchTermAndElements,
filterStudentnumbersByAccessrights,
findByCourseAndSemesters
}
@@ -156,12 +156,12 @@ const getAllStudyrightElementsAndAssociations = async () => {
}
const getStudyrightElementsAndAssociationsForUser = async username => {
const studyrightelements = await getUserElementDetails(username)
if (studyrightelements.length === 0) {
const studyrightelementcodes = await getUserElementDetails(username)
if (studyrightelementcodes.length === 0) {
return []
}
const associations = await getAssociatedStudyrights(studyrightelements.map(element => element.code))
return formatStudyrightElements(studyrightelements, associations)
const associations = await getAssociatedStudyrights(studyrightelementcodes)
return formatStudyrightElements(studyrightelementcodes, associations)
}
const getAllDegreesAndProgrammes = async () => {
@@ -187,6 +187,11 @@ const getAllProgrammes = async () => {
return elementDetails
}
const getAllElementDetails = async () => {
const elementDetails = ElementDetails.findAll()
return elementDetails
}
const associatedStudyrightElements = async (offset, limit) => {
const studyrights = await Studyright.findAll({
attributes: [],
@@ -355,8 +360,7 @@ const getFilteredAssociations = async (codes) => {
}
const getUserAssociations = async (userid) => {
const elements = await getUserElementDetails(userid)
const codes = elements.map(e => e.code)
const codes = await getUserElementDetails(userid)
const associations = await getFilteredAssociations(codes)
return associations
}
@@ -375,5 +379,6 @@ module.exports = {
getFilteredAssociations,
getUserAssociations,
refreshAssociationsInRedis,
getAllProgrammes
getAllProgrammes,
getAllElementDetails
}
@@ -1,9 +1,13 @@
const sequelize = require('sequelize')
const { Op } = sequelize
const moment = require('moment')
const { flatMap } = require('lodash')
const { Credit, Student, Course, Provider, Studyright, StudyrightElement,
ElementDetails, ThesisCourse, ThesisTypeEnums
ElementDetails, Transfers
} = require('../models')
const {
ThesisCourse, ThesisTypeEnums
} = require('../models/models_kone')
const { studentnumbersWithAllStudyrightElements } = require('./populations')
const { semesterStart, semesterEnd } = require('../util/semester')
const isNumber = str => !Number.isNaN(Number(str))
@@ -169,30 +173,39 @@ const graduatedStatsForStudytrack = async (studytrack, since) => {
return graduatedStatsFromStudyrights(studyrights)
}
const findProgrammeThesisCredits = code => Credit.findAll({
include: {
model: Course,
required: true,
const findProgrammeThesisCredits = async code => {
const thesiscourses = await ThesisCourse.findAll({
model: ThesisCourse,
where: {
programmeCode: code
}
})
const courseCodeToThesisCourse = thesiscourses.reduce((acc, tc) => { acc[tc.courseCode] = tc; return acc }, {})
const credits = await Credit.findAll({
include: {
model: ThesisCourse,
model: Course,
required: true,
where: {
programmeCode: code
code: {
[Op.in]: thesiscourses.map(tc => tc.courseCode)
}
}
},
where: {
credittypecode: {
[Op.ne]: 10
}
}
},
where: {
credittypecode: {
[Op.ne]: 10
}
}
}).map(credit => {
const { id, course, attainment_date } = credit
const { code, thesis_courses } = course
const { thesisType: type } = thesis_courses[0]
const year = attainment_date && attainment_date.getFullYear()
return { id, code, type, year }
})
})
return credits.map(credit => {
const { id, course, attainment_date } = credit
const { code } = course
const year = attainment_date && attainment_date.getFullYear()
return { id, code, type: courseCodeToThesisCourse[code].thesisType, year }
})
}
const thesisProductivityFromCredits = credits => {
const stats = {}
@@ -215,9 +228,25 @@ const thesisProductivityForStudytrack = async code => {
}
const combineStatistics = (creditStats, studyrightStats, thesisStats, creditsForMajors, transferredCredits) => {
const stats = { ...creditStats }
Object.keys(stats).forEach(year => {
const allYears = [
...new Set(
flatMap(
[
creditStats,
studyrightStats,
thesisStats,
creditsForMajors,
transferredCredits
],
Object.keys
)
)
]
const stats = {}
allYears.forEach(year => {
const thesis = thesisStats[year] || {}
stats[year] = {}
stats[year] = creditStats[year] || { credits: 0, year }
stats[year].graduated = studyrightStats[year] ? studyrightStats[year].graduated : 0
// stats[year].medianGraduationTime = studyrightStats[year] ? studyrightStats[year].medianGraduationTime : 0
stats[year].bThesis = thesis.bThesis || 0
@@ -273,16 +302,18 @@ const creditsAfter = (studentnumbers, startDate) => {
}
const thesesFromClass = async (studentnumbers, startDate, code) => {
return Credit.findAll({
const thesiscourses = await ThesisCourse.findAll({
where: {
programmeCode: code
}
})
const credits = await Credit.findAll({
include: {
model: Course,
required: true,
include: {
attributes: ['thesisType'],
model: ThesisCourse,
required: true,
where: {
programmeCode: code
where: {
code: {
[Op.in]: thesiscourses.map(tc => tc.courseCode)
}
}
},
@@ -297,12 +328,16 @@ const thesesFromClass = async (studentnumbers, startDate, code) => {
[Op.in]: studentnumbers
}
}
}).reduce((acc, curr) => {
curr.course.thesis_courses.map(th => {
acc[th.thesisType] = acc[th.thesisType] ? acc[th.thesisType] + 1 : 1
})
})
const courseCodeToThesisCourse = thesiscourses.reduce((acc, tc) => { acc[tc.courseCode] = tc; return acc }, {})
const courseCodes = credits.map(c => c.course.code)
const theses = courseCodes.reduce((acc, code) => {
const thesisType = courseCodeToThesisCourse[code].thesisType
acc[thesisType] = acc[thesisType] ? acc[thesisType] + 1 : 1
return acc
}, {})
return theses
}
const graduationsFromClass = async (studentnumbers, studytrack) => {
@@ -345,49 +380,32 @@ const gendersFromClass = async (studentnumbers) => {
}, {})
}
const countriesFromClass = async (studentnumbers) => {
const nationalitiesFromClass = async (studentnumbers) => {
return Student.findAll({
attributes: [[sequelize.fn('count', sequelize.col('country_en')), 'count'], 'country_en'],
where: {
studentnumber: {
[Op.in]: studentnumbers
},
}
},
group: ['country_en'],
raw: true
}).reduce((acc, curr) => {
acc[curr.country_en] = curr.count
attributes: ['home_country_en']
}).reduce((acc, { home_country_en }) => {
const country = home_country_en || 'Unknown'
if (!acc[country]) acc[country] = 0
acc[country] += 1
return acc
}, {})
}
const tranferredToStudyprogram = async (studentnumbers, startDate, studytrack, endDate) => {
return Studyright.findAndCountAll({
include: {
include: {
model: ElementDetails,
where: {
type: {
[Op.eq]: 20
}
}
},
model: StudyrightElement,
required: true,
where: {
code: {
[Op.eq]: studytrack
},
startdate: {
[Op.gt]: moment(startDate).add(1, 'days'), // because somehow startdates have a time that is not 00:00
[Op.lt]: new Date(endDate)
}
}
},
return Transfers.count({
where: {
student_studentnumber: {
studentnumber: {
[Op.in]: studentnumbers
}
},
transferdate: {
[Op.between]: [startDate, endDate]
},
targetcode: studytrack
}
})
}
@@ -461,9 +479,9 @@ const statsForClass = async (studentnumbers, startDate, studytrack, endDate) =>
graduationsFromClass(studentnumbers, studytrack),
thesesFromClass(studentnumbers, startDate, studytrack),
gendersFromClass(studentnumbers),
countriesFromClass(studentnumbers),
tranferredToStudyprogram(studentnumbers, startDate, studytrack, endDate),
endedStudyright(studentnumbers, startDate, studytrack, endDate)
endedStudyright(studentnumbers, startDate, studytrack, endDate),
nationalitiesFromClass(studentnumbers)
])
}
@@ -485,13 +503,13 @@ const throughputStatsForStudytrack = async (studytrack, since) => {
mte150: 0,
},
genders: {},
countries: {},
thesisM: 0,
thesisB: 0,
students: 0,
graduated: 0,
inTargetTime: 0,
transferred: 0
transferred: 0,
nationalities: {}
}
const years = getYears(since)
// studyprogramme starts with K if bachelors and M if masters
@@ -515,14 +533,12 @@ const throughputStatsForStudytrack = async (studytrack, since) => {
const studentnumbers = await studentnumbersWithAllStudyrightElements([studytrack], startDate, endDate, false, false)
const creditsForStudyprogramme =
await productivityCreditsFromStudyprogrammeStudents(studytrack, startDate, studentnumbers)
const [credits, graduated, theses, genders, countries, transferredTo, endedStudyright] =
const [credits, graduated, theses, genders, transferredTo, endedStudyright, nationalities] =
await statsForClass(studentnumbers, startDate, studytrack, endDate)
//console.log(year)
//console.log(transferredFrom.rows.map(r => r.get({ plain: true })))
// theres so much shit in the data that transefferFrom doesnt rly mean anything
delete genders[null]
delete countries[null]
const creditValues = credits.reduce((acc, curr) => {
acc.mte30 = curr >= 30 ? acc.mte30 + 1 : acc.mte30
acc.mte60 = curr >= 60 ? acc.mte60 + 1 : acc.mte60
@@ -539,10 +555,9 @@ const throughputStatsForStudytrack = async (studytrack, since) => {
totals.genders[genderKey] + Number(genders[genderKey]) :
Number(genders[genderKey])
})
Object.keys(countries).forEach(countryKey => {
totals.countries[countryKey] = totals.countries[countryKey] ?
totals.countries[countryKey] + Number(countries[countryKey]) :
Number(countries[countryKey])
Object.keys(nationalities).forEach(nationality => {
if (!totals.nationalities[nationality]) totals.nationalities[nationality] = 0
totals.nationalities[nationality] += nationalities[nationality]
})
const graduationTimes = graduated.map(g => moment(g.enddate).diff(g.studystartdate, 'months'))
const inTargetTime = graduationTimes.filter(time =>
@@ -556,7 +571,7 @@ const throughputStatsForStudytrack = async (studytrack, since) => {
totals.ended = totals.ended + endedStudyright.count,
totals.medianGraduationTime = median(allGraduationTimes)
totals.inTargetTime = totals.inTargetTime + inTargetTime
totals.transferred = totals.transferred + transferredTo.count
totals.transferred = totals.transferred + transferredTo
return {
year: `${year}-${year + 1}`,
credits: credits.map(cr => cr === null ? 0 : cr),
@@ -567,13 +582,12 @@ const throughputStatsForStudytrack = async (studytrack, since) => {
thesisM: theses.MASTER || 0,
thesisB: theses.BACHELOR || 0,
genders,
countries,
creditValues,
transferred: transferredTo.count,
ended: endedStudyright.count
transferred: transferredTo,
ended: endedStudyright.count,
nationalities
}
}))
return { id: studytrack, status: null, data: { years: arr, totals } }
}
@@ -11,7 +11,8 @@ const {
thesisProductivityFromCredits,
thesisProductivityForStudytrack
} = require('./studytrack')
const { sequelize, ThesisTypeEnums } = require('../models')
const { sequelize } = require('../models')
const { ThesisTypeEnums, ThesisCourse } = require('../models/models_kone')
const { readFileSync } = require('fs')
const { MASTER, BACHELOR } = ThesisTypeEnums
@@ -19,9 +20,15 @@ const { MASTER, BACHELOR } = ThesisTypeEnums
const provider = '500-M010'
const studytrack = 'MH50_010'
const thesisCourse = {
// from studytrack.test.sql
programmeCode: 'MH50_010', courseCode: 'THESIS_01', thesisType: MASTER
}
beforeAll(async () => {
const query = readFileSync('./src/services/studytrack.test.sql', 'utf8')
await sequelize.query(query)
await ThesisCourse.create(thesisCourse)
})
test('Credits for provider should contain passed course credit', async () => {
@@ -16,7 +16,7 @@ BEGIN
VALUES
(5, ts, ts)
;
INSERT INTO course
("code", "name", "is_study_module")
VALUES
@@ -25,14 +25,14 @@ BEGIN
(course_02, '{ "en": "COURSE_EN" }', 'false'),
(thesis, '{ "en": "Bachelor thesis" }', 'false')
;
INSERT INTO credit_types
("credittypecode", "createdAt", "updatedAt")
VALUES
(10, ts, ts),
(4, ts, ts)
;
INSERT INTO credit
("id", "createddate", "lastmodifieddate", "semestercode", "course_code", "credittypecode", "attainment_date", "credits")
VALUES
@@ -44,14 +44,14 @@ BEGIN
('CREDIT_06', ts, ts, 5, course_01, 4, date_2015, 5),
('CREDIT_07', ts, ts, 5, thesis, 4, date_2015, 30)
;
INSERT INTO providers
("providercode", "createdAt", "updatedAt")
VALUES
(provider_01, ts, ts),
(provider_02, ts, ts)
;
INSERT INTO course_providers
("coursecode", "providercode", "createdAt", "updatedAt")
VALUES
@@ -84,8 +84,4 @@ BEGIN
(12, studytrk_02, ts, ts)
;
INSERT INTO thesis_courses
("programmeCode", "courseCode", "thesisType", "createdAt", "updatedAt")
VALUES
(studytrk_01, thesis, 'MASTER', ts, ts);
END $$;
END $$;
@@ -1,11 +1,11 @@
const Sequelize = require('sequelize')
const { Tag } = require('../models')
const { Tag } = require('../models/models_kone')
const Op = Sequelize.Op
const findTags = () => Tag.findAll({})
const findTagsByStudytrack = (studytrack) => {
const findTagsByStudytrack = async (studytrack) => {
return Tag.findAll({
where: {
studytrack: {
@@ -15,6 +15,17 @@ const findTagsByStudytrack = (studytrack) => {
})
}
const findTagsFromStudytrackById = async (studytrack, tag_ids) => {
return Tag.findAll({
where: {
studytrack,
tag_id: {
[Op.in]: tag_ids
}
}
})
}
const createNewTag = async (tag) => {
return Tag.create(tag)
}
@@ -33,5 +44,6 @@ module.exports = {
createNewTag,
findTags,
findTagsByStudytrack,
findTagsFromStudytrackById,
deleteTag
}
@@ -1,5 +1,5 @@
const Sequelize = require('sequelize')
const { TagStudent, Tag } = require('../models')
const { TagStudent, Tag } = require('../models/models_kone')
const Op = Sequelize.Op
@@ -33,12 +33,15 @@ const createStudentTag = async (tag) => {
return TagStudent.create(tag)
}
const deleteStudentTag = async (id) => {
const createMultipleStudentTags = async (tags) => {
return TagStudent.bulkCreate(tags, { ignoreDuplicates: true })
}
const deleteStudentTag = async (studentnumber, tag_id) => {
return TagStudent.destroy({
where: {
id: {
[Op.eq]: id
}
tag_id,
studentnumber
}
})
}
@@ -48,5 +51,6 @@ module.exports = {
getStudentTagsByStudentnumber,
getStudentTagsByStudytrack,
createStudentTag,
createMultipleStudentTags,
deleteStudentTag
}
@@ -1,5 +1,5 @@
const { Op } = require('sequelize')
const { Teacher, Credit, Course, Semester, Provider, CourseGroup } = require('../models/index')
const { Teacher, Credit, Course, Semester, Provider } = require('../models/index')
const splitByEmptySpace = str => str.replace(/\s\s+/g, ' ').split(' ')
@@ -40,11 +40,6 @@ const bySearchTerm = async (rawTerm) => {
codeLike(terms),
matchesId(searchTerm)
]
},
include: {
model: CourseGroup,
attributes: ['id', 'name'],
required: false
}
})
}
@@ -93,7 +88,7 @@ const markCredit = (stats, passed, failed, credits, transferred) => {
...stats,
credits: transferred ? stats.credits : stats.credits + credits,
passed: stats.passed + 1,
transferred: transferred ? stats.transferred + credits : stats.transferred
transferred: transferred ? stats.transferred + credits : stats.transferred
}
} else if (failed) {
return {
@@ -1,4 +1,4 @@
const { ThesisCourse } = require('../models/index')
const { ThesisCourse } = require('../models/models_kone')
const createThesisCourse = (programme, course, type) => ThesisCourse.create({
programmeCode: programme,
@@ -1,5 +1,6 @@
const { forceSyncDatabase } = require('../database/connection')
const { Course, ElementDetails, ThesisTypeEnums, ThesisCourse } = require('../models')
const { Course, ElementDetails } = require('../models')
const { ThesisTypeEnums, ThesisCourse } = require('../models/models_kone')
const { createThesisCourse, deleteThesisCourse, findProgrammeTheses } = require('./thesis')
const courseOne = {
@@ -0,0 +1,80 @@
const axios = require('axios')
const { UPDATER_URL } = require('../conf-backend')
const client = axios.create({ baseURL: UPDATER_URL })
const ping = async () => {
const url = '/ping'
const response = await axios.get(url)
return response.data
}
const updateStudents = async (studentNumbers) => {
const response = await client.post('/update', studentNumbers)
return response.data
}
const updateOldestStudents = async (amount) => {
const response = await client.post('/update/oldest', { amount })
return response.data
}
const updateAllStudents = async () => {
const response = await client.post('/update/all')
return response.data
}
const updateActiveStudents = async () => {
const response = await client.post('/update/active')
return response.data
}
const updateNoStudents = async () => {
const response = await client.post('/update/no_student')
return response.data
}
const updateMetadata = async () => {
const response = await client.post('/update/meta')
return response.data
}
const updateAttainments = async () => {
const response = await client.post('/update/attainment')
return response.data
}
const updateStudentlist = async () => {
const response = await client.post('/update/studentlist')
return response.data
}
const getStatuses = async () => {
const response = await client.get('/statuses')
return response.data
}
const rescheduleScheduled = async () => {
const response = await client.post('/reschedule/scheduled')
return response.data
}
const rescheduleFetched = async () => {
const response = await client.post('/reschedule/fetched')
return response.data
}
module.exports = {
ping,
updateStudents,
updateOldestStudents,
updateAllStudents,
updateActiveStudents,
updateMetadata,
updateAttainments,
updateStudentlist,
getStatuses,
rescheduleScheduled,
rescheduleFetched,
updateNoStudents
}
@@ -1,6 +1,6 @@
const _ = require('lodash')
const moment = require('moment')
const { UsageStatistic } = require('../models')
const { UsageStatistic } = require('../models/models_kone')
const Sequelize = require('sequelize')
const { Op } = Sequelize
@@ -1,6 +1,7 @@
const axios = require('axios')
const { USERSERVICE_URL } = require('../conf-backend')
const UnitService = require('./units')
const elementDetailService = require('./elementdetails')
const client = axios.create({ baseURL: USERSERVICE_URL, headers: { 'secret': process.env.USERSERVICE_SECRET } })
@@ -15,11 +16,6 @@ const findAll = async () => {
return response.data
}
const findAllEnabled = async () => {
const response = await client.get('/findallenabled')
return response.data
}
const login = async (uid, full_name, hyGroups, affiliations, email) => {
const response = await client.post('/login', {
uid, full_name, hyGroups, affiliations, email,
@@ -43,7 +39,8 @@ const byUsername = async (uid) => {
const getUserElementDetails = async (username) => {
const url = `/user/elementdetails/${username}`
const response = await client.get(url)
return response.data
const elementdetailcodes = response.data
return elementDetailService.byCodes(elementdetailcodes)
}
const byId = async (id) => {
@@ -89,12 +86,15 @@ const setFaculties = async (uid, faculties) => {
}
const getUnitsFromElementDetails = async username => {
const url = `/user/elementdetails/${username}`
const response = await client.get(url)
const elementDetails = response.data
const elementDetails = await getUserElementDetails(username)
return elementDetails.map(element => UnitService.parseUnitFromElement(element))
}
const getCodesFromElementDetails = async uid => {
const elementDetails = await getUserElementDetails(uid)
return elementDetails.map(e => e.code)
}
const modifyAccess = async (body) => {
const response = await client.post('/modifyaccess', body)
return response.data
@@ -105,6 +105,11 @@ const getAccessGroups = async () => {
return response.data
}
const getAccessGroupCodesFor = async (user) => {
const response = await client.get(`/get_accessgroupcodes/${user}`)
return response.data
}
module.exports = {
ping,
byUsername,
@@ -117,10 +122,11 @@ module.exports = {
enableElementDetails,
removeElementDetails,
findAll,
findAllEnabled,
modifyAccess,
getAccessGroups,
getAccessGroupCodesFor,
getUnitsFromElementDetails,
getCodesFromElementDetails,
getRolesFor,
setFaculties
}
@@ -17,6 +17,21 @@ const getStudentNumberChecksum = studentNumber => {
return (10 - (checksum % 10)) % 10
}
const isValidStudentId = (id) => {
if (/^0\d{8}$/.test(id)) {
// is a 9 digit number
const multipliers = [7, 1, 3, 7, 1, 3, 7]
const checksum = id
.substring(1, 8)
.split('')
.reduce((sum, curr, index) => {
return (sum + curr * multipliers[index]) % 10
}, 0)
return (10 - checksum) % 10 == id[8]
}
return false
}
// helpers to print complex sequelizedata
const plainPrint = (sequelizeData) => console.log(JSON.parse(JSON.stringify(sequelizeData)))
@@ -33,5 +48,6 @@ module.exports = {
getStudentNumberChecksum,
plainPrint,
plainify,
isValidStudentId,
oldToNew
}
@@ -1,6 +1,6 @@
const Transport = require('winston-transport')
const uuid = require('uuid')
const { UsageStatistic } = require('../models')
const { UsageStatistic } = require('../models/models_kone')
module.exports = class LogSaverTransport extends Transport {
log(payload, callback) {
@@ -16,7 +16,7 @@ module.exports = class LogSaverTransport extends Transport {
status: payload.status,
data: payload
}
UsageStatistic.create(object)
}
callback()
@@ -2,7 +2,6 @@ const { requiredGroup } = require('../conf-backend')
const hasRequiredGroup = (hyGroups) => {
const hasGroup = requiredGroup === null || hyGroups.some(e => e === requiredGroup)
console.log('has required group?:', hyGroups, requiredGroup, hasGroup)
return hasGroup
}
@@ -3,19 +3,18 @@ process.env.DB_SCHEMA = schema
const test = require('ava')
const supertest = require('supertest')
const jwt = require('jsonwebtoken')
const { sequelize } = require('../../src/models')
const app = require('../../src/app')
const conf = require('../../src/conf-backend')
const api = supertest(app)
const uid = 'tktl', fullname = ''
const payload = { userId: uid, name: fullname, enabled: true }
const token = jwt.sign(payload, conf.TOKEN_SECRET, {
expiresIn: '24h'
})
// const jwt = require('jsonwebtoken')
// const conf = require('../../src/conf-backend')
// const uid = 'tktl', fullname = ''
// const payload = { userId: uid, name: fullname, enabled: true }
// const token = jwt.sign(payload, conf.TOKEN_SECRET, {
// expiresIn: '24h'
// })
test.before(async () => {
await sequelize.createSchema(schema)
@@ -1,4 +1,5 @@
const { sequelize } = require('../../src/models/index')
const { sequelizeKone } = require('../../src/models/models_kone')
const { redisClient } = require('../../src/services/redis')
const { forceSyncDatabase } = require('../../src/database/connection')
const { seedAllMigrations } = require('../../src/database/seed_migrations')
@@ -10,5 +11,7 @@ beforeAll(async () => {
afterAll(async () => {
await sequelize.close()
await redisClient.quitAsync()
await sequelizeKone.close()
// https://stackoverflow.com/a/54560610
await new Promise(res => redisClient.quit(() => setImmediate(res)))
})
@@ -3,6 +3,7 @@ const {
Studyright, Credit, StudyrightExtent, Semester
} = require('../../../src/models/index')
const { optimizedStatisticsOf } = require('../../../src/services/populations')
jest.setTimeout(10000)
const langify = name => ({
en: `${name}_en`,
@@ -58,7 +59,8 @@ const semesters = {
const createQueryObject = (year, semester, codes, months) => ({
studyRights: codes,
year,
endYear: year,
startYear: year,
semesters: [semester],
months
})
@@ -211,7 +213,7 @@ describe('optimizedStatisticsOf tests', () => {
expect(
courseinstances.some(instance =>
(instance.date.getTime() === courseinstanceFall.coursedate.getTime()) &&
(instance.course.code === courseinstanceFall.course_code))
(instance.course.code === courseinstanceFall.course_code))
).toBe(true)
})
@@ -2,7 +2,7 @@ const test = require('ava')
const supertest = require('supertest')
const app = require('../../src/app')
const api = supertest(app)
const { sequelize } = require('../../src/models')
const { sequelizeKone } = require('../../src/models/models_kone')
const conf = require('../../src/conf-backend')
const jwt = require('jsonwebtoken')
@@ -22,9 +22,9 @@ test.before(async () => {
expiresIn: '24h'
})
//console.log(token)
sequelize.query(
`DELETE
FROM tag_student
sequelizeKone.query(
`DELETE
FROM tag_student
WHERE tags_tagname = 'test3'`
)
})
@@ -33,7 +33,7 @@ test.after.always(async () => {
const tagToAdd = { text: 'mooc-2013' }
console.log('ennd bfefore')
let res = await api
await api
.delete('/api/students/014424850/tags')
.send(tagToAdd)
.set('x-access-token', token)
@@ -186,7 +186,6 @@ test.only('new api populations can be fetched', async t => {
.expect('Content-Type', /application\/json/)
const stats = res.body
console.log(stats)
t.is(stats.length, 6)
})
@@ -1,12 +0,0 @@
module.exports = {
up: async (queryInterface, Sequelize) => {
return queryInterface.addColumn('users', 'language',
{
type: Sequelize.STRING,
defaultValue: 'fi'
})
},
down: (queryInterface) => {
return queryInterface.removeColumn('users', 'language')
}
}
@@ -1,8 +0,0 @@
module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.addColumn('credit', 'attainment_date', { type: Sequelize.DATE })
},
down: async (queryInterface) => {
queryInterface.removeColumn('credit', 'attainment_date')
}
}
@@ -1,10 +0,0 @@
module.exports = {
up: async (queryInterface) => {
queryInterface.addIndex('credit', {
fields: ['courseinstance_id'],
name: 'credit_courseinstance_id'
})
},
down: async () => {
}
}
@@ -1,19 +0,0 @@
module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.addColumn(
'credit',
'course_code',
{
type: Sequelize.STRING,
references: {
model: 'course',
key: 'code',
foreignKey: 'credit_course_fkey'
},
}
)
},
down: async (queryInterface) => {
await queryInterface.removeColumn('credit', 'course_code')
}
}
@@ -1,15 +0,0 @@
module.exports = {
up: async (queryInterface) => {
await queryInterface.sequelize.query(`
UPDATE credit
SET
attainment_date = ci.coursedate,
course_code = ci.course_code
FROM courseinstance ci
WHERE ci.id = credit.courseinstance_id
;
`)
},
down: async () => {
}
}
@@ -1,10 +0,0 @@
module.exports = {
up: async (queryInterface) => {
await queryInterface.addIndex('credit', {
fields: ['course_code'],
name: 'credit_course_code'
})
},
down: async () => {
}
}
@@ -1,12 +0,0 @@
module.exports = {
up: async (queryInterface, Sequelize) => {
return queryInterface.addColumn('filters', 'description',
{
type: Sequelize.STRING,
defaultValue: ''
})
},
down: (queryInterface) => {
return queryInterface.removeColumn('filters', 'description')
}
}
@@ -1,10 +0,0 @@
module.exports = {
up: async (queryInterface) => {
await queryInterface.addIndex('credit', {
fields: ['attainment_date'],
name: 'credit_attainment_date'
})
},
down: async () => {
}
}
@@ -1,10 +0,0 @@
module.exports = {
up: async (queryInterface) => {
await queryInterface.addIndex('semester_enrollments', {
fields: ['studentnumber'],
name: 'semester_enrollment_studentnumber'
})
},
down: async () => {
}
}
@@ -1,14 +0,0 @@
module.exports = {
up: async (queryInterface) => {
try {
await queryInterface.addIndex('transfers', {
fields: ['studentnumber'],
name: 'transfers_studentnumber'
})
} catch (e) {
console.log('transfers_studentnumber index in table transfers already existed')
}
},
down: async () => {
}
}

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