Compare commits

...

442 Commits

Author SHA1 Message Date
a8dd5bc142 fix(day): fix #2347 by adding repeated examiner check to day consistency check for day exam occurrences 2025-02-24 18:37:39 +01:00
134f18641d chore(profile): show examiners in profile data, towards #2347 2025-02-24 17:10:54 +01:00
515eddc032 chore(exams): allow email for exam result entry as well 2025-02-24 16:12:22 +01:00
89b0d87bde fix(widgets): fix erroneous whitespace in name widget 2025-02-24 15:34:04 +01:00
c51fb7ea7d Merge branch '145-build-system-rewrite' into fradrive/merge-rewrite-jost 2025-02-20 17:42:38 +01:00
bf4a79a8ec Merge branch '145-build-system-rewrite' into fradrive/merge-rewrite-jost 2025-02-20 16:41:02 +01:00
d46fb9e928 chore(profile): towards exam table in profile data (WIP)
towards #2347
2025-02-20 16:06:15 +01:00
bc0dbd26fc chore(tutorial): assigning exam occurrences may check duplicate examiners
towards #2347
2025-02-20 14:54:29 +01:00
10a4d11022 chore(tutorial): user view warns against duplicate examiners
towards #2347
2025-02-20 11:10:24 +01:00
0fa70b6e1f refactor(admin): problem caching indicator made human readable 2025-02-14 17:01:54 +01:00
98c2189b54 Revert "Merge branch '145-build-system-rewrite' into fradrive/merge-jost-new-build"
This reverts commit 0a6340844f, reversing
changes made to b4f3171257.
2025-02-14 11:51:20 +01:00
0a6340844f Merge branch '145-build-system-rewrite' into fradrive/merge-jost-new-build 2025-02-14 09:33:19 +01:00
b4f3171257 chore(avs): add debug log info after not finding an error in company supervision switching after avs update 2025-02-13 17:26:10 +01:00
38baa395e2 fix(linter): disable unnecessary linter warning 2025-02-13 17:20:49 +01:00
cfbb489db4 chore(firm): finalize supervision discrepancy view 2025-02-13 13:03:48 +01:00
8a17c0e368 fix(build) 2025-02-13 13:03:06 +01:00
f6a98b2e59 chore(firm): filter working on supervision discrepancy view 2025-02-12 17:02:04 +01:00
39d705b380 chore(admin): minor reorder admin problem page 2025-02-12 17:01:16 +01:00
d84269154f refactor(db): widen the type for DBRead for more flexibility
also
- change some AdminProblemR DB actions to DBRead instead
- add insane supervision warning to AdminProblem page
2025-02-12 12:11:08 +01:00
396bcf6e13 chore(firm): add working view for supervision discrepancy by firm
show if a supervisionship-company is unrelated to either supervisor or supervisee
2025-02-11 18:08:41 +01:00
a56a5e148e chore(lms): fix #2605
- Implement a mechanism that deletes those users after a short while
- Never delete numerical LMS logins
- Allow admins to terminate an E-Learning manually
- Option to terminate E-Learning upon longtime renewal
- Detection of unnecessary E-Learning (i.e. long valid durations)
2025-02-11 14:38:40 +01:00
102cd6c73e fix(lms): do not delete orphans with all numerical idents
lms idents with all numerical idents are used for testing and thus should not be deleted, even if orphaned
2025-02-11 12:26:43 +01:00
2a3a776b13 chore(lms): add longter,m validity filter, towards #2605 2025-02-11 10:05:16 +01:00
434549c945 fix(avs): updateReceivers should not re-insert formerly known receivers 2025-02-10 17:37:14 +01:00
274cd21e79 chore(mail): view page for receivers working now and polished 2025-02-10 17:28:06 +01:00
305839ad5d chore(mail): add i18n for mail receivers view 2025-02-07 16:02:51 +01:00
e3bdabce1b Added de-de-formal.hamlet for receivers 2025-02-07 09:01:42 +00:00
39a4ebef2a chore(mail): add modal computing actual receivers at postal pref columns 2025-02-06 19:02:04 +01:00
cc7abf9a94 chore(firm): add company preference for email pin passwords
companies may be set such that their users have no email pin password by default
switching to such a company deletes the pin password
2025-02-05 17:43:43 +01:00
3b1d5f3af7 chore(lms): implement lms termination action
also:
- track last LmsSate for orphans
- make note searchable

towards #2605
2025-02-05 14:38:04 +01:00
995e75da8e fix(audit): add user id who caused company superior change to audit log 2025-02-05 13:29:42 +01:00
dcbd7c096c fix(tutorial): truly fix #2696 template choice respects school, course, term, etc.
Template course names may contain Vorlage or Template and the type in any order somewhere within the name
2025-02-04 16:28:54 +01:00
8f03862a6d refactor(lms): use runDBRead and caching for FilterColumnHandler used in LMS Orphans 2025-02-04 15:05:30 +01:00
2566afaec1 chore(lms): complete view for orphaned lms logins
towards #2605
2025-02-04 13:17:23 +01:00
572ad4afa1 chore(lms): add note to orphans and create working filter 2025-02-04 09:53:15 +01:00
b78bd7971a fix(build): remove erroneous + from settings.yml 2025-02-03 18:12:18 +01:00
a8a1f5607b chore(lms): add route and breadcrumbs for lms oprhan view 2025-02-03 18:10:21 +01:00
3a6b3bc9f2 chore(lms): create stub for lms oprhan view 2025-02-03 16:46:23 +01:00
347a69670e refactor(lms): ensure days/months in qualification settings are always used correctly and implement settings for orphans
- extensive refactoring for qualification lms settings
- qualificationAuditDuration changed from months to days
- qualificationAuditDuration no longer optional
- qualificationAuditDuration is only used for LMS; clarified
- three new settings:
    + orphan-deletion-days:
    + orphan-deletion-batch:
    + orphan-deletion-repeat-hours:
2025-02-03 15:43:36 +01:00
38fc071b8d chore(lms): register and display orphaned LMS idents
towards #2605
2025-01-31 17:31:21 +01:00
7ddc15dd0b chore(avs): test AVSneo problems
AVSneo will no longer have unique AVS CardNo: PersonSearch will return one card per company, all having the same CardNo, but possibly different colors

Test shows that FRADrive will handle this just fine, provided the old AVS workaround firing several requests at once remain in place
2025-01-31 15:15:47 +01:00
29af94206e fix(i18n): disambiguate between course-type and type of course both in german and english
- english: course type -> course category = Kursart
- german: Art des Kurses-> Kurstyp = Tutorial-Type
2025-01-31 14:45:55 +01:00
7d9be73844 fix(avs): prevent empty contact and status queries 2025-01-31 13:53:29 +01:00
3f40dd890e fix(tutorial): fix #2696 template choice respects school, course, term, etc. 2025-01-31 12:18:34 +01:00
7a1732507f refactor(lms): remove now obsolete lms edit stub 2025-01-30 19:05:41 +01:00
a76a23b9e2 refactor(i18n): make SomeMessages more flexible to distinguish it from UniWorXMessages, deprecated the latter 2025-01-30 18:53:49 +01:00
7c1df8a261 fix(hlint): remove superfluous dollar 2025-01-30 17:38:25 +01:00
17df5fd5cf chore(tutorial): convenience button to show tutorial exam results
required new filter on exam participants page
2025-01-30 17:34:31 +01:00
42a60a2725 various minor code refactors 2025-01-30 12:59:14 +01:00
710d0b6f71 chore(qualification): finish qualification edit handler 2025-01-29 18:12:34 +01:00
3cbb0452cb chore(form): create calendarDiffDaysField 2025-01-28 18:45:13 +01:00
37a15672c9 chore(qualification): prepare stub for edit handler
also fix some minor navigation issues
2025-01-28 16:35:56 +01:00
4f745d4676 refactor(UniWorxMessages): eliminate superfluous whitespace
also: some tutorial code cleaning
2025-01-28 11:03:03 +01:00
c059473cf4 refactor(tutorial): fix and complete exam occurrence form function 2025-01-27 17:40:13 +01:00
7503a55039 refactor(tutorial): exam occurrence form function and appearance 2025-01-24 17:28:58 +01:00
516e8cc849 refactor(tutorial): exam occurrence editing received specialised page 2025-01-15 17:59:24 +01:00
b2a5bb715a chore(tutorial): add separate exam occurrence edit page (WIP) 2025-01-14 18:28:31 +01:00
d275e465c8 chore(exam): add convenience function to duplicate exam occurrences to another day 2025-01-13 19:26:43 +01:00
3faf8017b6 chore(exam): auto name generation for examOccurrences 2025-01-13 17:53:22 +01:00
c903b84082 chore(tutorial): add covenience button to full exam editing 2025-01-10 17:50:09 +01:00
b095b4feed fix(tutorial): fix exam occurrence form
works better, but still not 100%
some debugging added
2025-01-09 19:24:35 +01:00
f954ebce43 chore(tutorial): switch relevant exams from registerFrom/To to examStart/End
registering is of users/supervisors, but this page is for admins, so  examStart/examEnd are only relevant for when it is actually happening
2025-01-09 12:57:33 +01:00
be0b90d0a1 chore(tutorial): towards #2347 exam occurrence form design finished, but buggy somehow (WIP)
Propably due to multiActionAForm badly interacting with contained massInputForm
2025-01-09 12:48:09 +01:00
17d64e218b chore(pathpiecel): PathPiece instance for lists of exam occurrence ids
towards #2347
2025-01-09 10:15:33 +01:00
c218a55be8 chore(tutorial): towards #2347 exam occurrence form mostly working (WIP)
form is completed, but the initial call needs proper arguments from DB about all apropriate exams
2025-01-08 19:01:59 +01:00
d37d39301c chore(tutorial): towards #2347 exam occurrence form added (WIP) 2025-01-08 15:28:10 +01:00
8b52f00fb0 chore(tutorial): towards #2347 add convenience buttons to add exam tutorial (STUB)
This is STUB add a multiform action that is not yet evaluated. Form Handler is to be implemented next.
2024-12-19 17:56:21 +01:00
f9562c4a32 chore(tutorial): assign exam rooms for tutorial users ad hoc 2024-12-19 15:57:49 +01:00
2e3c51562b refactor(saltine): fix hlint and ghc warnings 2024-12-19 09:13:00 +01:00
032a344ed1 Merge branch 'fradrive/merge-jost-new-build' of https://dev.azure.com/fraport/Fahrerausbildung/_git/FRADrive into fradrive/merge-jost-new-build 2024-12-18 09:17:14 +01:00
52f361c24e refactor(daily): move caching into own submodule
we need those methods in Handler.Tutorial.Users as well
2024-12-18 09:06:39 +01:00
fc4cd49ca7 build(Makefile): use YESOD_IP_FROM_HEADER to fix reverse-proxy issues 2024-12-16 17:40:48 +01:00
5524f4da4a build(docker/backend): switch to official stack snapshot image 2024-12-16 17:40:48 +01:00
bd8630472b refactor: backport saltine (0.2.0.0->0.1.1.1) for compatibility with proper lts-18.0 stack snapshot image 2024-12-16 17:40:48 +01:00
0d13d3b2fd ci(azure-pipelines): tweak PROJECT_DIR and MOUNT_DIR 2024-12-16 17:38:58 +01:00
a33dcd2b19 ci(azure-pipelines): add PROJECT_DIR and MOUNT_DIR build-args 2024-12-16 17:38:58 +01:00
311cb0e3e3 build(docker/backend): tmp-remove more deps 2024-12-16 17:38:58 +01:00
00036a7f58 build(docker/backend): remove unused dependency 2024-12-16 17:38:58 +01:00
84e2323cc6 build(docker/backend): tmp-remove deps 2024-12-16 17:38:58 +01:00
0862d9e90c build(docker/backend): remove test-only dependencies temporarily 2024-12-16 17:38:58 +01:00
0273ed6a40 build(docker/backend): remove locales (and thus tzdata) installs for testing purposes 2024-12-16 17:38:58 +01:00
f0557f927f build(docker/backend): add temporary tools FROM for pipeline test 2024-12-16 17:38:58 +01:00
d47f1902b8 build(docker/backend): remove unused dependency 2024-12-16 17:38:58 +01:00
623cc91c22 build(docker/backend): add debug print for apt sources info 2024-12-16 17:38:58 +01:00
268ad6b8a6 build(docker/backend): add texlive-base and more tex runtime dependencies 2024-12-16 17:38:58 +01:00
dd78d9388d build(Makefile): revisit stop targets 2024-12-16 17:38:58 +01:00
92a43ac131 chore(daily): add function to retrieve all exam occurrences for given days
the function uses the memcachedByClass mechanism, which was slightly refined as well to include the class within the memcached keys for added correctness
2024-12-13 17:27:02 +01:00
ed70a92856 refactor(form): make all userField variants consistent with each other 2024-12-13 16:21:53 +01:00
eab6b6363d chore(exam): show exam occurrences in participants views for tutorial and course 2024-12-12 18:28:15 +01:00
6d172c8259 chore(exam): add examiner to occurrence options
we intend to use the exam examiner for adding occurrences through tutorials
2024-12-09 17:38:34 +01:00
f81a99d224 fix(form): knownUserField not working as intended (WIP) 2024-12-06 14:16:24 +01:00
19a05e9940 Merge branch '145-build-system-rewrite' into fradrive/merge-jost-new-build 2024-12-06 12:44:14 +01:00
130140b60d fix(form): knownUserField not working as intended (WIP) 2024-12-06 12:41:18 +01:00
d6de55a886 refactor(form): knownUserField not working as intended (WIP) 2024-12-05 18:17:34 +01:00
a454ac9d32 chore(form): add knownUserField accepting known users only 2024-12-04 18:10:13 +01:00
127138f4c4 fix(fill): exam prefill dates work now 2024-12-04 11:58:50 +01:00
f6933cf3ae fix(hlint): implement hlint suggestion 2024-12-03 11:58:30 +01:00
9123f61b2e chore(daily): implement left-over todos and i18n 2024-12-03 11:56:48 +01:00
031c0b0f29 fix(icons): fix some botched icon definitions, for real 2024-12-02 18:12:53 +01:00
a1ae491b89 Merge branch 'fradrive/merge-jost-new-build' of https://dev.azure.com/fraport/Fahrerausbildung/_git/FRADrive into fradrive/merge-jost-new-build 2024-12-02 17:54:38 +01:00
7f5651466d fix(icons): fix some botched icon definitions 2024-12-02 17:53:40 +01:00
9a7e09b852 Merged PR 15163: GHCI fix
Move GHCI fix to local development branch

Related work items: #2397
2024-12-02 16:52:49 +00:00
44a60bcef6 chore(daily): fix #2349 completing daily sanity check 2024-12-02 13:28:33 +01:00
e051557d3e chore(daily): towards #2347 check complete, except i18n
also missing: displaying memcached check results in each line of day view
2024-11-29 18:13:30 +01:00
97db5caff9 chore(daily): towards #2347 by caching and sorting results 2024-11-29 16:19:16 +01:00
9d4dde069c chore(daily): towards #2347 by implementing basic check for one user
also prepare for caching results and show on daily page, if existing
2024-11-29 13:32:04 +01:00
612a931d36 chore(daily): towards #2347 by performing AVS queries/updates
actual checking of retrieved values is still a todo
2024-11-28 17:04:59 +01:00
ce164f308f chore(daily): add proper btn for consistency check 2024-11-27 17:56:16 +01:00
8ffa8ef852 chore(daily): add stub for consistency check 2024-11-27 17:18:34 +01:00
6c50758800 fix(hlint): implement some hlint suggestions 2024-11-27 17:12:32 +01:00
89aa49b100 chore(job): disable jobworkers in development in order to reduce log output 2024-11-27 17:04:35 +01:00
5e3118f33f chore(daily): properly implement note suggestion caching and invalidation 2024-11-27 16:04:34 +01:00
2af3ffb73a chore(daily): basic functionality #1939 completed and checked
- filters now work as intended
- textField suggestions now work as intended
2024-11-27 12:56:29 +01:00
df3f60709e fix(icon): add missing icon 2024-11-26 18:03:57 +01:00
59b945ce4c chore(daily): adjust css, improve suggestions 2024-11-26 18:03:43 +01:00
7d8f8e0dfc Merge remote-tracking branch 'origin/145-build-system-rewrite' into fradrive/merge-jost-new-build 2024-11-26 08:48:16 +01:00
74279b67df chore(day): attempt to fix participant note suggestions 2024-11-25 11:45:12 +01:00
08b38af137 chore(daily): add suggestions to note fiels (WIP) 2024-11-22 18:54:08 +01:00
50d034586e refactor(daily): user company discrepancies 2024-11-21 17:59:10 +01:00
7a1f4b5a5f fix(daily): form submit now works as intended 2024-11-20 18:03:36 +01:00
eab39bc5db minor adjustments to routes and icons 2024-11-20 18:03:05 +01:00
f731d80342 Merge remote-tracking branch 'origin/145-build-system-rewrite' into fradrive/merge-jost-new-build 2024-11-18 16:24:29 +01:00
b32724e533 Merge remote-tracking branch 'origin/145-build-system-rewrite' into fradrive/merge-jost-new-build 2024-11-14 08:55:49 +01:00
507c383410 Merge remote-tracking branch 'origin/145-build-system-rewrite' into fradrive/merge-jost-new-build 2024-11-11 16:47:35 +01:00
aebf6ec914 Merge remote-tracking branch 'origin/145-build-system-rewrite' into fradrive/merge-jost-new-build 2024-11-11 14:34:43 +01:00
bccdb2494f fix(msg): minor uni2wok to fradrive message change
Primarly done to the the new build environment start-backend file watcher and see whether a restart enables the website
2024-11-11 13:26:57 +01:00
36b4beb908 Merge remote-tracking branch 'origin/145-build-system-rewrite' into fradrive/merge-jost-new-build 2024-11-11 12:31:38 +01:00
228a6254bc Merge remote-tracking branch 'origin/144-build-system-rewrite' into fradrive/merge-jost-new-build 2024-11-11 11:43:18 +01:00
7294b9731c fix(doc): Update outdated GitLab references to DevOps work items 2024-11-05 11:08:44 +01:00
97a3845f6d chore(firm): add action to add non-avs firm associates 2024-11-04 18:20:43 +01:00
0adc12c828 fix(doc): minor haddock fixes 2024-10-30 17:18:11 +01:00
28c3ee5be1 chore(day): complete form columns for daily view (untested)
unfortunately `make start` does not enter DEVELOPMENT mode currently, so this is not yet testeted.
2024-10-29 18:16:29 +01:00
8c91d6d37a chore(day): make form columns compile eventually 2024-10-29 13:38:23 +01:00
0d6346ef2c chore(icons): add instructions on how to add icons 2024-10-28 17:48:41 +01:00
fddbf8a30b fix(icons): add missing icons 2024-10-28 17:44:17 +01:00
3d63c88c75 chore(day): add missing form columns 2024-10-28 16:11:45 +01:00
c92ddb9081 Merge remote-tracking branch 'origin/fradrive/jost'into 'fradrive/merge-jost-new-build' 2024-10-28 12:05:37 +01:00
1b71137295 chore(tutorial): (WIP) towards #90 write form columns 2024-10-23 16:12:18 +02:00
6fcfe56626 fix(test): fix test problem and add tests for UserEyeExam and UserDrivingPermit 2024-10-23 15:47:20 +02:00
030ddcac66 fix(build) 2024-10-22 14:39:58 +02:00
36a0bd9edc chore(tutorial): show additional columns for #90
columns are distinguished by user and the entities given in parenthesis:
- driving permit (tutorial)
- eye exam (tutrial)
- tutorial note (tutorial)
- attendance (tutorial & day)
- attendance-note (tutorial & day)
- parking permit (day)
2024-10-22 12:39:34 +02:00
06fa34c938 chore(tutorial): build model for #90 2024-10-21 15:59:32 +02:00
d4d511a02f fix(room): deduplicate room column and fix order 2024-10-17 16:48:09 +02:00
ec2b09b20b chore(daily): show rooms for tutorial lessons 2024-10-15 17:48:36 +02:00
7d57a30be7 refactor(TH): minor code clean up 2024-10-15 11:03:01 +02:00
01c4225da4 refactor(TH): add sqlMIXproj' using reify on TableExpr for more comfort 2024-10-14 19:16:36 +02:00
4fc6f54b32 chore(TH): add sqlMIXproj to improve dbTable usage, also add card-nos to DayTask Table 2024-10-14 18:27:44 +02:00
8506c4d7e0 refactor(memcached): checking memcached key security mechanisms
RESULTS:

Keys for memcached use their Binary representation!

This means that the following three are all interchangeable as a key:
      newtype Foo1 = Foo1 { someInt1 :: Int } deriving newtype (Binary)
      data    Foo2 = Foo2 { someInt2 :: Int } deriving         (Binary)
      type    Foo3 = Int
Therefore it is best to use $(memcachedHere) or $(memcachedByHere) if possible or add another type
2024-10-11 11:23:29 +02:00
ed44edc199 chore(daily): show course associated qualifications 2024-10-09 18:11:22 +02:00
ab46577b7e fix(avs): fix #225 by skipping firm updates entirely if AVS FirmInfo is unchanged for previously seen values for AVS User to be updated 2024-10-09 12:21:31 +02:00
be7fc2e540 fix(avs): avs firm update no longer may update wrong company
Note: noticed while working on #225
2024-10-09 11:47:46 +02:00
3960931bb5 fix(avs): fix #224 repeated superior changes no longer occur
furthermore AdminProblems are only inserted if the same problem does not exist unsolved
2024-10-08 17:47:46 +02:00
56c2be7b79 refactor(occurrences): fold RoomReference into Occurrences, completed 2024-10-08 13:01:44 +02:00
4e171a7a1a fix(memcached): using memcachedHere did not compile due to staging problems 2024-10-08 10:08:04 +02:00
f642b9cccf fix(occurrences): room occurrence form works now 2024-10-07 18:31:02 +02:00
72b2b6876b fix(test): add arbitrart instances and adjust argument changes to tests 2024-10-07 12:58:22 +02:00
c9ecb30542 fix(build): occurrences no longer have a READ instance 2024-10-04 16:16:32 +02:00
8ddf38b904 chore(build): limit max compile cpu cores to 5 2024-10-04 16:13:40 +02:00
21592347b4 chore(occurrences): workaround provide simple room field with least recent suggestions 2024-10-04 16:13:01 +02:00
e625dca6ea refactor(memcached): remove ARC cache and LRU logic some more
more leftover dead code was removed, especially cache prewarm options that no longer had an effect on a non-existing ARC cache
2024-10-04 12:19:27 +02:00
f17d89c21e chore(occurrences): add GIN index for JSONB columns 2024-10-02 15:52:08 +02:00
5c7b4cff93 refactor(occurrences): fix migration 2024-09-30 16:05:33 +02:00
83fe750b15 refactor(occurrences): remove RoomReference from model and add migration 2024-09-30 13:56:45 +02:00
e29e6f3db8 refactor(occurrences): fold RoomReference into Occurrences (WIP)
Each Occurrence now has its own RoomReference, i.e. Mondays may have a different Room assigned than Tuesdays

WIP Problem: occurrencesAFrom does not work, always insists on Room missing
2024-09-24 17:15:15 +02:00
6dd27eb848 fix(build): minor 2024-09-24 13:10:14 +02:00
4c2baa4e9f fix(occurrences): occurringLessons had an erroneously inverted condition 2024-09-24 13:05:16 +02:00
384c39b9ec chore(occurrences): add datatype LessonTime for dealing timetable intervals 2024-09-24 11:21:33 +02:00
a262921a7d refactor(memcached): remove ARC cache entirely
NOTE: this was a crude surgery, removing everything ARC related; some dead code artifacts may have remained.

Especially check PrewarmCacheConf

Reason for removall: adding `memcachedInvalidateClass` was difficult to implement with ARC active; ARC was known to be problematic; removal was easier (see #2 2024-09-23)
2024-09-23 18:52:26 +02:00
05638c2b51 chore(memcached): add key classes for easy invalidation 2024-09-23 17:09:47 +02:00
3d7df8066d refactor(daily): factor our tutorial selection function 2024-09-18 18:03:49 +02:00
6c9d92475e fix(firm): filtering by active supervisor working 2024-09-17 17:59:58 +02:00
78c645cf21 fix(lpr): print log sorting works now 2024-09-17 17:58:52 +02:00
e8b276851c fix(build) 2024-09-17 12:58:13 +02:00
e16baedfce refactor(model): move JSONB instance to proper module 2024-09-17 12:57:31 +02:00
d19266e918 chore(lpr): improve lpr log display 2024-09-17 12:56:49 +02:00
53c68638da chore(daily): make company a property of TutorialParticipant, towards #90 2024-09-16 17:16:19 +02:00
6e3dd1c1f3 chore(daily): add more columns #90 2024-09-13 18:03:41 +02:00
ba0fd21c8f chore(daily): add page actions #90 2024-09-13 16:18:38 +02:00
d0eb3ddf92 refactor(jsonb): change DB using JSONB, to improve stub #90 2024-09-13 13:39:38 +02:00
5307350b0b chore(daily): improve stub #90 change DB to JSONB (WIP) 2024-09-12 17:46:38 +02:00
1a954e037f chore(daily): create stub in preparation for #90 2024-09-11 17:44:09 +02:00
faaaa18247 refactor(map): clarify some unnecessarily obfuscated code
also, using Map.fromList is more efficient if the list happens to be ordered
2024-09-11 17:43:56 +02:00
2e0455a154 chore(config): add config/develop-settings.yml only active if DEVELOPMENT
Ensure that certain settings are NOT seen in production, but automatically active in development without using environment variables.
2024-09-11 13:11:31 +02:00
6a070a6775 fix(supervision): fix #181 by unifying deletion of supervision 2024-09-10 17:47:09 +02:00
ea113cf57a chore(login): limit number of suggestions for dummy development login for convenience 2024-09-10 17:45:27 +02:00
6ffc49ae0e chore(avs): auto licence synch preview show AVS-No as well 2024-09-10 12:36:52 +02:00
ab8b17229a chore(health): show db time on status page and status time diffs in a human readable format 2024-09-09 16:41:43 +02:00
74f7633837 fix(notifications): fix #180 qualification expiry notification are sent only once 2024-09-09 15:34:41 +02:00
ade27e6479 fix(avs): fix #178 by deleting old superiors for individual users 2024-09-05 17:53:18 +02:00
cbadef0a73 chore(mail): fix #179 reorder attachments and guess PDF pin password in Text display 2024-09-05 16:28:20 +02:00
2a27a1efa6 fix(avs): fix #124 avs auto synch filter working
also, provide test facility for auto synch
2024-09-05 16:27:10 +02:00
620e3e4700 fix(mail): fix #179 by adding download links for PDF attachments 2024-09-05 14:09:50 +02:00
f0798e8836 chore(avs): debug automatic avs licence synch within admin avs test page 2024-09-04 18:08:08 +02:00
3c5edb1b97 fix(avs): typo in superior remark, towards #178 2024-09-04 16:29:12 +02:00
4f7855b9ee fix(avs): acs auto synch had inverted success/failure
also: some minor typo fixes
2024-09-03 12:53:51 +02:00
1e896da4a3 chore(avs): prepare superior update shortcircuit for future 2024-09-02 09:08:44 +02:00
7e5c256b4c fix(avs): company superiors are now irregular supervisors and old ones are deleted
DETAILS:

Superiors:
- Superiors do not become Company-Default-Supervisors automatically
- Superiors become irregular supervisors without rerouting, existing supervisions are not changed
- Superiors become company users at equal-to-max priority, if not already

For each AVN User update:
- if superior change for unchanged company:
    all company supervisions with remark "Vorgesetzter" are removed
    create admin problem that notifies about superior change (special if new superior could not be created)
- all company associates are irregularly supervised by the new superior with remark "Vorgesetzer"

Questions:
 - company had superior, but no longer: just remove superior-supervisions, do not report admin problem?
 - Problem: superior changed, but we first encounter this through a user changing company. Change is not detected at this point, old superiors remain until an old company associate is updated too
2024-08-30 17:41:33 +02:00
43319fbcca chore(admin): unreachable page offers convient avs and ldap synch buttons 2024-08-29 18:12:10 +02:00
f946e99da3 fix(ldap): no more timeout for ldap synch all button 2024-08-29 16:45:39 +02:00
cfe2318f81 fix(avs): attempt LDAP upsert before creating avs users 2024-08-29 16:15:16 +02:00
64ff002ffb chore(firm): provide more filters for supervisors
also fix build #175
2024-08-29 14:34:37 +02:00
8397c468a0 fix(firm): fix #175 by separating superiors in firm tables and selections 2024-08-28 17:50:44 +02:00
81721b0794 chore(status): improve readability of time spans 2024-08-28 10:45:11 +02:00
40dadd5876 fix(firm): fix #174 by adding address search filter to all company view 2024-08-28 10:44:27 +02:00
b7e5b8f111 fix(model): flip erroneous boolean SQL default for CompanyPostalAddress
changing this SQL default value now is admittedly too late, as the damage is already done, but documents the right default value nevertheless
2024-08-28 09:55:57 +02:00
8ec2875590 fix(avs): switch company did not always increase priority 2024-08-27 16:23:42 +02:00
9c82558d71 fix(user): fix pagination and count for supervision tables 2024-08-26 17:40:57 +02:00
e8f9c21b7c chore(problem): admin problem filtering works on full text now 2024-08-26 15:17:01 +02:00
109e845db6 chore(problem): towards admin problem filtering 2024-08-22 17:44:19 +02:00
53abdb7cc3 chore(health): augement #154 by adding option to disable interface warnings
Also:
- add usage explanation
- show intervals in a human readable form
2024-08-22 17:28:28 +02:00
407ba543a1 chore(health): fix #154 by adding interface warning threshold edit handler 2024-08-21 17:34:19 +02:00
f61c35cfe7 refactor(companies): mark table columns showing only prime company as such, fix #5
- also improve performance by changing dbtProj/selectList into a subselect
- fix #5 no longer sensible, as most are single values to be displayed right away
2024-08-21 11:52:29 +02:00
b0972bb154 fix(mail): display html emails no longer distorts page
html is filtered once through pandoc, as proposed in #2
2024-08-20 12:35:16 +02:00
8bc3663ee2 fix(linter): minor bug in exam-correct.hs 2024-08-19 17:52:11 +02:00
be5e609b1f fix(build): minor linter fix 2024-08-12 18:01:59 +02:00
cc5da9a2a9 fix(avs): fix #124 implement automatic avs driving licence synchronisation 2024-08-12 18:01:04 +02:00
e551fadd29 chore(sql): add regex match for sql 2024-08-12 12:36:27 +02:00
2ed626ea4a chore(avs): towards #124 add filter for multiple firm users with block reason '%firm%'
- also add warning to admin avs licence difference for AVS R licence holders about to be changed
2024-08-09 18:33:23 +02:00
f4823aaf28 refactor(avs): switch some runDB to runDBRead 2024-08-09 17:59:14 +02:00
760b102d52 chore(avs): flag AVS R-holders about to be revoked
- flag on admin problem view
- exempt from automatic avs licence synch for levels below 3
2024-08-09 17:01:10 +02:00
000d8100db chore(avs): towards #124 add jobworker for AVS licence synch (WIP) 2024-08-08 18:19:09 +02:00
d209a110e8 refactor(linter): implement minor hlit suggestion 2024-08-08 17:30:03 +02:00
0af8598d6d chore(release): 27.4.76 2024-08-08 17:01:07 +02:00
c3d27c25b5 chore(mail): add decoder for MIME encoded word 2024-08-08 16:52:02 +02:00
1e6547e903 refactor(comm): clean CommCenterR and MailCenterR handlers and unify these 2024-08-08 13:56:10 +02:00
e4abf915ee Merge branch 'fradrive/jost' into 'master'
add comm center for email/letter notification overview

Closes #171, #150, #148, #149, and #173

See merge request fradrive/fradrive!36
2024-08-07 19:16:37 +00:00
6299612adc refactor: various minor changes, mostly some comments 2024-08-07 17:51:33 +02:00
8f54ea1051 refactor(qualifications): unify qualification selectField mechanics 2024-08-07 17:50:38 +02:00
c1dbd61c14 chore(mail): minor code cleanup mailCenterR
-- hiding currently unneded dbtForm
-- slightly better formatting for MIME encoded word
2024-08-07 13:52:47 +02:00
e35a5e99a6 fix(user): format userDisplayNames having umlaut substitutes with respect to userSurname correctly
we often have displayNames like "Steffen Joest" and surname "Jöst" which were previously displayed as "Steffen Joest (**Jöst**)" and which are now displayed as "Steffen **Jöst**".

Also, the case of surname is left unchanged, while the displayName is converted to title
2024-08-07 11:44:39 +02:00
ab00a4f665 chore(mail): fix #171 by adding a route for all notifications to users and displaying them 2024-08-06 17:42:27 +02:00
f929e03129 fix(build): linter likes it 2024-08-05 18:17:00 +02:00
21d32fd4cf chore(mail): mail display towards #171 2024-08-05 18:15:56 +02:00
4df8bd2fa5 chore(mail): stub towards #171
new routes /mail and /mail/show/UUID to eventually display all sent emails by the system
2024-08-02 18:28:16 +02:00
d1fa01fcc5 fix(avs): towards #117 update if current value is Nothing even if oldval == newval
Damit sollten zumindest die ganzen NULL Fälle bein einem neuen Update erledigt sein. Unklar, wo diese aber herkamen.
2024-08-02 16:13:09 +02:00
ec02767552 fix(course): fix #150 no longer allow duplicated associated qualifications and orders due to editing existing 2024-08-02 15:40:25 +02:00
cfd25348ad fix(course): fix #148 course qualification ordering
some refactoring done along the way, fixing a bug in relation to #150 as well
2024-08-01 17:45:18 +02:00
e1419766f3 fix(course): fix #149 course cloning proposes associated qualifications
This commit required a massInput form, using massInputAccumEditA, which turned out to difficult to use.
2024-08-01 17:09:05 +02:00
5b6e4e60e7 fix(course): fix #150 course edit for associated qualifications requires school admin or lecturer rights 2024-08-01 11:41:27 +02:00
bc47387c91 fix(course): WIP course cloning should propose same associated qualifications, towards #149 2024-07-31 19:03:30 +02:00
0fde59c19a chore(profile): show user courses among enrolled course type list
(Recall: course = tutorial, course type = course)
2024-07-31 17:51:13 +02:00
507a7e02fc fix(avs): using firm superior as UserEmail is a no-go due to uniqueness constraints
Thus, we do not save the firm superior as `UserEmail` any more. The firm superior email is still used as a fallback for `CompanyEmail` which in turn is used as a fallback email, if a `CompanyUser` has no valid email at all.
2024-07-31 15:03:26 +02:00
43f5c5f485 fix(avs): fix #173 by not using firm superior email as display email
Instead, a valid firm superior email is used as `UserEmail` so that it can be used as a fallback address.
2024-07-31 14:16:40 +02:00
b9f70c7796 chore(avs): ensure supervisor reroutes are correct upon company switch 2024-07-30 15:58:12 +02:00
6ccbb3b7ff refactor(ldap): some minor code cleaning 2024-07-30 15:57:43 +02:00
8b0466e74e fix(ap): disambiguate action message 2024-07-30 15:56:45 +02:00
689e6347da chore(print): make apc ident comparison fuzzy
received and stored idents are additionally accepted as infixes of one another, if the length difference is less than 3 characters
2024-07-30 10:42:39 +02:00
11fdcf0d44 fix(lms): max e-learning tries default removed and info added to lms overview 2024-07-29 14:58:19 +02:00
58152beb03 refactor(utils): flip arguments bsnoc 2024-07-29 11:29:58 +02:00
803e8bfedb chore(release): 27.4.75 2024-07-12 17:16:10 +02:00
d853e8559b fix(lms): allow 2nd reminders to be independent of renewal period 2024-07-12 17:14:48 +02:00
e6f0454e78 Merge branch 'fradrive/newletter' 2024-07-12 14:01:12 +02:00
8c8ffa5183 chore(avs): remove company superior, if there is none anymore 2024-07-12 13:44:21 +02:00
fee14edf36 refactor(firm): fix #157 refactor duplicated code
also ensures that supervisor default reaons filters are obeyed.
2024-07-12 12:21:17 +02:00
0bbb679a43 chore(profile): indicate linked postal addresses 2024-07-12 12:12:26 +02:00
6063eb24a2 chore(email): qualfication renewal email add info about renewal options
Also mention that this email reminder may be ignored for users who have already mage arrangements
2024-07-12 11:32:12 +02:00
28e2739e51 fix(firm): fix #157 by removing redundant duplicated code in firm user and supervision handling 2024-07-11 18:37:40 +02:00
c17c18f924 fix(build): make linter happy again 2024-07-11 15:28:58 +02:00
d65fb2f4cd chore(firm): add reason for user company association 2024-07-10 15:54:15 +02:00
ab28c8c243 fix(build): minor 2024-07-10 12:27:51 +02:00
6e2d545772 chore(users): allow profile edits with invalid display_email address, if unchanged 2024-07-10 12:23:37 +02:00
fa0541aa4e fix(job): change some queueJob' to queueJob instead 2024-07-10 11:47:01 +02:00
b5215cc7e8 fix(nix): workaround parsing port numbers failed in nix-shell 2024-07-10 11:45:59 +02:00
a1668f891a fix(users): nameHtml no longer complains about differing case for surname and displayname 2024-07-09 17:06:33 +02:00
c813c665ed fix(users): remove users with company post address from list of unreachable users 2024-07-09 11:56:58 +02:00
9a0e8988fa refactor(health): avoid duplicate interface health check speficiations 2024-07-09 10:45:30 +02:00
9d3198f49b chore(health): avoid duplicate interface health check speficiations 2024-07-08 18:11:46 +02:00
2caa5aec5b chore(health): add option to mark certain interface health checks to remain indefinitely 2024-07-08 15:34:19 +02:00
3def8ca916 chore(letter): add number of tries as qualification property 2024-07-08 14:22:54 +02:00
a97c3a5c9d fix(lms): send second reminder indepentently from renewal period 2024-07-08 14:21:25 +02:00
468af9de9d fix(lms): move lms reuse info from QualificationR to LmsR
LmsR is intended to be seen by Fraport Admins only, while QualificationR is intended to be seen by Supervisors (in the future).

The LMS reuse information might confuse non-admins and is irrelevant to them.
2024-07-05 17:40:12 +02:00
91e21db758 chore(release): 27.4.74 2024-07-04 15:35:41 +02:00
6ea3a30afc Merge branch 'fradrive/newletter' 2024-07-04 14:40:03 +02:00
3a66bed173 chore(firm): towards #169 distinct icon for avs firm superior (user-tie) 2024-07-04 14:38:31 +02:00
f869a829d2 fix(lms): fix #161 lms for multiple joint qualifications 2024-07-04 14:15:05 +02:00
b9b1d3e57b chore(release): 27.4.73 2024-07-03 17:59:41 +02:00
93196a6400 Merge branch 'fradrive/newletter' 2024-07-03 17:57:40 +02:00
feb8d92bc1 chore(log): add more filter options to admin problem log 2024-07-03 17:56:13 +02:00
073432c75b chore(letter): allow for more different driving licence names in letters 2024-07-03 16:50:38 +02:00
0725a9a908 chore(lms): towards #169 option to prevent qualifications to renew automatically upon e-learning 2024-07-03 15:51:42 +02:00
0ac75e0d59 fix(letter): rephrase some minor letter parts 2024-07-03 15:46:08 +02:00
62d698503d chore(release): 27.4.72 2024-07-02 18:17:21 +02:00
9e2a964ef7 Merge branch 'fradrive/newletter' 2024-07-02 18:16:48 +02:00
357e943f21 chore(avs): towards #169 - filter users by last avs synch 2024-07-02 18:15:27 +02:00
5bf85394d4 fix(avs): towards #169 - superiors are elevated to max priority for that company
this entails that users may have multiple equal priority companies
2024-07-02 18:14:54 +02:00
99f03078a1 chore(db): use runDBRead more often 2024-07-02 17:37:34 +02:00
7ca3237ad0 chore(profile): towards #169
- only one matrikelnumber
- proper update indication for matrikelnumber and pin
- only display tables with data in profile
- refactor supervision overviews
2024-07-02 16:55:12 +02:00
9e2f2214ce fix(avs): do not associate users by AvsInfoPersonEmail 2024-07-02 15:27:56 +02:00
ff9014ce05 fix(avs): fix superfluous quotes for matriculation numbers on newly created users 2024-07-02 13:20:34 +02:00
622c01b9be chore(profile): towards #169
-  profile supervison streamlined (WIP)
2024-07-01 18:04:25 +02:00
6d49ea092b chore(profile): towards #169
- distinguished reroute icon
- profile cleaned/reordered
2024-07-01 16:24:38 +02:00
d4f3ce7bf3 fix(firm): supervisor secondary did not work as intended
also, adding company link to secondary supervisors
2024-06-28 11:26:55 +02:00
8b03409554 chore(release): 27.4.71 2024-06-27 19:59:08 +02:00
45bc5ca9f5 chore(firm): various contributions towards #157 2024-06-27 17:42:13 +02:00
3dfc7f8c8b fix(doc): fix erroneous unintentional haddock annotations 2024-06-27 16:48:47 +02:00
e25a8569c5 chore(lms): add action to manually enqueue qual holder for e-learning 2024-06-27 16:29:25 +02:00
37efc89e07 fix(avs): company superior emails become company wide supervisors 2024-06-27 12:40:35 +02:00
975bf13d9c chore(avs): proper company superiors as company wide default APs (WIP) 2024-06-26 17:18:41 +02:00
2559346d96 fix(avs): new AVS from existing LDAP user no longer misses fields 2024-06-26 15:08:38 +02:00
5f1af130ed fix(letter): convenience links working again 2024-06-26 15:07:19 +02:00
d4a0e1f201 fix(letter): adjust spacing, pin location and interpolation 2024-06-26 14:31:01 +02:00
47e56280fc fix(ldap): match mobile number better between LDAP and AVS 2024-06-26 14:07:52 +02:00
f108c6cfec fix(avs): match mobile number better between LDAP and AVS 2024-06-25 17:36:33 +02:00
e4fa1ddd68 fix(avs): priority for picking primary email demote superior 2024-06-25 15:54:55 +02:00
f8c36636ff fix(letter): expiry and valid dates were wrong 2024-06-25 14:11:50 +02:00
0a93f79f4e chore(db): new code for truncate table 2024-06-25 14:06:49 +02:00
b3d1dabfc2 refactor(profile): clean ui, reduce unnecessary routes 2024-06-25 11:16:20 +02:00
c212f2e8d7 fix(i18n): add missing translation for new primary company 2024-06-25 08:30:39 +02:00
2cc529be39 fix(i18n): add missing translation for new primary company 2024-06-25 08:30:29 +02:00
f425bd9afe chore(avs): add covenience clean up to avs admin person search 2024-06-24 11:30:17 +02:00
d161c296ad Merge branch 'master' into fradrive/newletter 2024-06-24 09:06:33 +02:00
b7ed7338d7 chore(release): 27.4.70 2024-06-21 23:35:42 +02:00
07663516e5 fix(build): hlint wants a newtype instead 2024-06-21 23:34:58 +02:00
18cdc52df0 fix(build): hlint wants a newtype instead 2024-06-21 23:33:58 +02:00
c04614ff86 chore(release): 27.4.69 2024-06-21 13:48:32 +02:00
766b8589d6 fix(avs): keep company on unchange address/email only if either is non-empty 2024-06-21 13:47:05 +02:00
f37c08099c chore(jobs): add option to manually delete old jobs 2024-06-21 13:45:08 +02:00
d7acc7a2d0 fix(avs): synch job deletes used row instead of truncation
Database.Esquelet.Utils.truncate is suspected to crash in conjunction with the incomplete argument containing an error value due to strictness
2024-06-21 13:09:16 +02:00
7ad7fe609c chore(avs): add more avs development test data 2024-06-21 11:55:54 +02:00
822c43c8a7 fix(avs): fix type causing avs surname upate not working 2024-06-21 08:45:16 +00:00
8721bdb3f3 fix(build): add missing license file 2024-06-21 09:02:56 +02:00
73aecc2df8 fix(print): fix #167 by sotring affected user in PrintJob 2024-06-20 18:22:35 +02:00
c38e87e1e0 fix(letter): switch markdown for renewal letter too 2024-06-20 17:47:17 +02:00
dfe4352575 chore(letter): switch to new letters
- contributes towards #64 and #82
2024-06-20 17:04:51 +02:00
a2a89a8aad refactor(letter): expiry letter updated 2024-06-20 16:17:52 +02:00
73ea2f54df chore(letter): complete parameterized englisch translation 2024-06-20 14:25:37 +02:00
34199a37fd chore(users): multiple name filter and remove subordinates 2024-06-20 12:58:34 +02:00
554c1eec27 chore(release): 27.4.68 2024-06-19 17:54:39 +02:00
e5cbd096ce Merge branch 'master' into fradrive/newletter 2024-06-19 17:53:16 +02:00
2ae11dc25c fix(letter): minor 2024-06-19 17:52:47 +02:00
d61788a1f5 chore(letter): update demo renewal letters 2024-06-19 17:41:14 +02:00
ab5e432b77 refactor(avs): use associated type family to consistently produce CheckUpdate 2024-06-19 15:10:23 +02:00
b5f5fb784c chore(release): 27.4.67 2024-06-17 17:53:05 +02:00
d83cb66c8b Merge branch 'fradrive/cr3' 2024-06-17 17:51:48 +02:00
a6d0105903 fix(avs): fix rare avs update bug involving values optional in avs but compulsory in user entity 2024-06-17 17:50:41 +02:00
cf019e6daa chore(letter): new letter generalisation WIP 2024-06-13 18:22:16 +02:00
0eac40457b chore(avs): add more auto update indicators to profile page 2024-06-13 14:51:05 +02:00
d1306303cf chore(release): 27.4.66 2024-06-12 17:51:47 +02:00
ad8e67dab1 Merge branch 'fradrive/cr3' 2024-06-12 17:51:15 +02:00
76e0710c7b fix(avs): fix #165 by updating userCompanyDepartmen and userCompanyPersonalNumer
- Die interne Firma Assoziation im User-Eintrag wird gelöscht, sobald der letzte erfolgreiche LDAP Sync älter ist als der eingestellte SYNCHRONISE_LDAP_EXPIRE (default = halbes Jahr).
- Firmen-Assoziation wird ebenfalls gelöscht, falls vorhanden
- Die Personalnummer bleibt erhalten, wenn das AVS diese noch liefert; ansonsten wird sie ebenfalls gelöscht.
- UserLdapPrimaryKey wird ggf. von AVS aktualisiert
2024-06-12 17:48:17 +02:00
a3beca87d1 chore(firm): filter associates by valid qualficiations
towards #157
2024-06-12 15:06:14 +02:00
996e6a0ce5 fix(avs): repeated avs sync enqueue no longe violates duplicate db uniqueness constraints 2024-06-12 11:47:23 +02:00
da74b95729 fix(avs): fix #164 by removing companyPersonalNumber and companyDepartment upon ldap sync expiry
SYNCHRONISE_LDAP_EXPIRE may be null (do nothing) or some seconds (15897600 = half a year). If no successful LDAP synch happened for the specified time, a successful AVS (sic!) update will delete the companyPersonalNumber and companyDepartment
2024-06-11 15:42:24 +02:00
f5754cd6b1 chore(users): add convenience buttons for ldap avs sync on profile page
towards #164
2024-06-11 15:22:24 +02:00
64b21d6fe6 chore(cache): add caching for simpleLinks and modal access 2024-06-11 12:53:17 +02:00
9fd80f2552 fix(avs): update email on manual company switch
towards #164
2024-06-11 12:12:56 +02:00
ac3271242d chore(firm): filter firm users by primary company
towards #157
2024-06-11 12:04:26 +02:00
7e022ca0a1 chore(release): 27.4.65 2024-06-10 18:43:50 +02:00
ab2e81f34d Merge branch 'fradrive/cr3' 2024-06-10 18:42:46 +02:00
e6c57035f9 chore(firm): only show/link primary company for a user in several places
contributes to #164
2024-06-10 18:40:58 +02:00
bb101dee7b fix(avs): company update no longer fails on duplicate key 2024-06-10 14:56:33 +02:00
e553ad4358 fix(avs): profile page correctly indicates automatic email and postal addresses 2024-06-07 17:42:05 +02:00
5b9d757ca4 chore(avs): person search triggers status and contact search for unique results for added convenience 2024-06-07 12:57:35 +02:00
aa1d230e49 fix(avs): steps towards #164
- link avs nr to status on profile page
- link companies on profile page
- swap icons for isAutomatic
- improve jsonWidget number display for integers and small floats
2024-06-07 12:31:54 +02:00
6acfd849ae fix(lette): adjust window for new pin letters 2024-06-05 12:02:23 +02:00
5a9ed747d2 chore(release): 27.4.64 2024-05-27 17:26:30 +02:00
396312092a Merge branch 'fradrive/cr3' 2024-05-27 17:23:12 +02:00
ea0fa9a3fa chore(avs): add more debug message for company updates failing 2024-05-27 17:21:28 +02:00
3fb2226204 chore(release): 27.4.63 2024-05-23 18:20:19 +02:00
b77e9e1d1c Merge branch 'fradrive/cr3' 2024-05-23 18:19:08 +02:00
9814712c61 refactor(letter): first test version of new letters 2024-05-23 18:18:13 +02:00
400d0a546e chore(shell): add correction utility script for frequent test bug 2024-05-23 18:15:02 +02:00
9451d90a9e fix(avs): company update checks uniques and ignores those updates if necessary 2024-05-23 17:08:30 +02:00
a732e26337 chore(release): 27.4.62 2024-05-19 09:01:59 +02:00
f47134c2f0 Merge branch 'fradrive/cr3' 2024-05-19 09:00:12 +02:00
ff2347b1c9 fix(avs): avs update on company shorthands working now 2024-05-17 18:06:16 +02:00
ccf9340449 fix(avs): deal gracefully with empty card status results 2024-05-17 12:05:08 +02:00
e5750ea7a0 chore(release): 27.4.61 2024-05-06 20:08:27 +02:00
7fd13677d3 Merge branch 'fradrive/cr3' 2024-05-06 20:01:26 +02:00
32a79ee2c9 Merge branch 'fradrive/cr3' of ssh://gitlab.uniworx.de/fradrive/fradrive into fradrive/cr3 2024-05-06 19:47:43 +02:00
6750798920 fix(build): add missing tex packages 2024-05-06 19:47:34 +02:00
3c4a0b86c1 fix(avs): fix #76 allowing company changes and fix #69 2024-05-06 19:35:59 +02:00
29182cb6dd chore(avs): switch company (WIP) 2024-05-06 16:58:58 +02:00
6084f92ad7 chore(avs): switch prime company 2024-05-06 16:33:57 +02:00
e2e5cc7bee chore(font): switch latex to roboto (WIP) 2024-05-06 16:33:42 +02:00
2fbd28154c fix(build): workaround non modal form result handler 2024-05-06 09:42:17 +02:00
21273e361a chore(avs): fix #76 allowing admins to switch to secondary company 2024-05-03 17:17:24 +02:00
5944efcb86 chore(avs): change to secondary company (WIP) form missing 2024-05-02 17:29:04 +02:00
fdbaa3c9d4 chore(avs): add function to change to secondary company 2024-04-30 17:45:29 +02:00
30807af3c4 chore(release): 27.4.60 2024-04-26 19:07:41 +02:00
f465cc9723 fix(build): type error in test db fill data 2024-04-26 18:43:22 +02:00
b8d41d10c9 Merge branch 'fradrive/cr3' 2024-04-26 18:14:17 +02:00
697979c277 fix(avs): fix #69 by redesigning live avs status page 2024-04-26 17:55:29 +02:00
a5dfd5e10f refactor(avs): add more logging to AVS synch ops 2024-04-26 16:04:28 +02:00
13a648de18 refactor(avs): first steps towards #69 2024-04-25 18:14:53 +02:00
6fd45f6896 refactor(avs): complete rewrite AVS synch
Three former background jobs could be removed
2024-04-25 17:07:12 +02:00
fea749f367 refactor(avs): rewrite AVS synch (WIP) 2024-04-25 09:55:40 +02:00
64a123387f fix(lint): remove minor superfluous dollar 2024-04-24 18:02:54 +02:00
2e4e1a94c9 refactor(avs): rewrite AVS synch (WIP) 2024-04-24 18:01:44 +02:00
a52c8a6ad7 fix(avs): several minor bugfixes
- See notes in #158 for details on update change policy
- fieldLensVal was not working
- create index for deleted table prevented start
- some hlint errors
2024-04-22 18:19:07 +02:00
fd6a5384d3 fix(qualification): fix #159 by removing an misleadingly named column for user qualification table
The columns QualificationUserLastNotified is misleading, since it only reflects notifications due to actual validity changes. This is necessary for the notification mechanism.

In case this column is reinstatiated, a better column name and a proper tooltip was added to the column.
2024-04-22 11:50:13 +02:00
4f8850b3b4 fix(avs): fix #36 and remove dead code 2024-04-18 18:30:23 +02:00
b7af6312f9 refactor(avs): complete createAvsUserById 2024-04-18 18:02:16 +02:00
234dd28f48 refactor(avs): rework fraport email recognition 2024-04-18 13:32:00 +02:00
890f8ad8b6 fix(i18n): fix some bad plurals 2024-04-17 12:14:58 +00:00
d56a1cdd46 fix(build): simple type error 2024-04-16 17:38:30 +02:00
cb2778e206 refactor(avs): rework createAvsUserById, dealing with supervision (WIP) 2024-04-16 17:31:55 +02:00
a373abad26 refactor(avs): safe old card-no to perform pdf pin pass updates 2024-04-16 12:56:03 +02:00
3b7762f451 refactor(avs): rework createAvsUserById (WIP) 2024-04-16 11:40:55 +02:00
54c08cc64b refactor(avs): rework upsertAvsUserByCard/Id 2024-04-12 17:27:46 +02:00
1f7c175a58 refactor(avs): rework guessAvsUser 2024-04-11 17:54:45 +02:00
4c29150371 chore(AVS): implement user avs update to primary company as outlined in graph in wiki 2024-04-08 18:31:29 +02:00
d213c8e4a1 chore(AVS): (WIP) implement user avs update to primary company 2024-03-22 12:24:08 +01:00
7a5917131c chore(avs): WIP properly update userCompany upon AVS change 2024-03-21 16:55:23 +01:00
1c5ca24dc5 chore(avs): WIP keep supervision if company keeps email or address 2024-03-20 18:07:27 +01:00
4a51f94a8f chore(avs): WIP update UserCompany accodring to AVS 2024-03-19 18:29:38 +01:00
b51f8a454a chore(log): display admin problem table with actions on admin problem view 2024-03-18 18:01:36 +01:00
08d2f8c2fc chore(log): add admin problem table 2024-03-13 18:00:39 +01:00
66eaa4f7dc fix(build): minor error non-development code 2024-03-13 11:23:25 +01:00
724e4a0bec fix(build): add import needed for production only 2024-03-13 08:30:54 +01:00
dcb947b1fb refactor(email): eliminate userAddress function due to user company linked email 2024-03-12 13:02:38 +01:00
09d10e1ba2 refactor(user): empty postal uses high priority company address instead working 2024-03-08 18:06:52 +01:00
9985151002 refactor(user): empty postal uses high priority company address instead (WIP) 2024-03-07 18:43:43 +01:00
c179c03f9d chore(avs): update company supervisors on avs user update 2024-03-06 13:41:18 +01:00
0b7175c26c refactor(avs): company upsert done
updating supervision is still a todo
2024-02-27 17:56:58 +01:00
c382be9325 fix(avs): invalidate contact cache after licence writes 2024-02-19 17:28:40 +01:00
d578e80282 fix(avs): disable caching by 0s no longer causes an exception 2024-02-19 10:57:09 +01:00
57a4aeb475 refactor(avs): remove need for undecideable super classes by simply using a sensible class definition 2024-02-19 09:39:06 +01:00
caf8e8b71e chore(avs): add remaining queries to new unifying class 2024-02-14 18:03:48 +01:00
66ef4066b3 chore(avs): undecidableSuperclasses to sidestep consequences of type erasure 2024-02-14 13:28:19 +01:00
b39f69df12 chore(avs): remove avs_cards, add generic queries WIP 2024-02-13 19:05:10 +01:00
ad2375b338 fix(avs): fix #152 by providing new online avs card filter throughout 2024-02-13 17:05:30 +01:00
ef36e22f76 chore(avs): make avs timeouts setting configurable 2024-02-13 16:25:58 +01:00
99adff80cd chore(avs): add timeout to cardno filter 2024-02-13 13:39:28 +01:00
ce4869f155 Merge branch 'master' into fradrive/cr3 2024-02-13 10:21:09 +01:00
64797536e3 refactor(qualification): card filter accepts multiple cards now 2024-02-13 10:05:50 +01:00
d4f7dce716 chore(avs): card no filter basic functionality WIP compiles 2024-02-12 19:02:57 +01:00
482dbe5c4e chore(dbtable): add FilterColumnIO and proof-of-concept
This commit adds a new type of filter to dbtables in module Pagination. The filter can perform an arbitrary IO action on its arguments before producing an sql/esqueleto filter expression.

Also, we turn some unnecessarily monadic code pure.
2024-02-07 17:38:53 +01:00
f5d57d9e5e Merge branch 'master' into fradrive/cr3 2024-01-26 10:01:48 +01:00
97471884f0 Merge branch 'master' into fradrive/cr3 2024-01-25 16:49:07 +01:00
9581e5513e Merge branch 'master' into fradrive/cr3 2024-01-25 13:19:34 +01:00
f439ea45af fix(build): migration needs to check for table existens first 2024-01-23 19:20:32 +01:00
de45731a9b refactor(company): supervison and company tables changed
- company avs id must be unique now, companies with id 0 are deleted
- user supervision can be annotated with company and or a reason, used to avoid accidental supervision relations; company supervision resets ignore non-company supervisions
2024-01-22 18:54:33 +01:00
f40448cd31 refactor(avs): minor code cleaning 2024-01-19 16:59:42 +01:00
9bf38d8198 chore(avs): email updating implemented 2024-01-18 17:19:44 +01:00
e8d66a4734 chore(avs): lenses for virtual avs fields created 2024-01-17 19:04:42 +01:00
45c3f11a83 chore(avs): add failure notices after contact update 2024-01-12 18:13:23 +01:00
cb807fce98 refactor(avs): using MaybeT 2024-01-12 16:57:17 +01:00
b5340a18a2 chore(avs): heterogeneous list working 2024-01-12 15:48:54 +01:00
83afdf760f fix(build): missing parameters added 2024-01-12 10:31:33 +01:00
61aba7e515 updateAvsUser (partial) requires migration 2024-01-11 19:23:35 +01:00
b566e59eb1 fix(firm): supervisor filter acts weird in test environment
no cause discerned, test in dev evironment were all fine. Maybe the sorting assumption wasn't right?

note other filters do not interfere with the memcaching in experiments
2023-12-21 17:26:46 +01:00
313 changed files with 14678 additions and 6995 deletions

View File

@ -1,65 +0,0 @@
# SPDX-FileCopyrightText: 2025 Sarah Vaupel <sarah.vaupel@uniworx.de>
#
# SPDX-License-Identifier: AGPL-3.0-or-later
parameters:
- name: releaseTag
type: string
- name: releaseEndpoint
type: string
default: 'devfra'
values:
- 'devfra'
- 'prodfra'
jobs:
- job: Release
displayName: Release ${{ parameters.releaseTag }}
container:
image: devfra.azurecr.io/de.fraport.build/tools:1.1.0
endpoint: devfra
steps:
# Download required artifacts from pipeline
- task: DownloadPipelineArtifact@2
displayName: Download FraDrive binaries
inputs:
artifactName: Build_backend
patterns: 'Build_backend/bin/*'
targetPath: '$(Build.Repository.LocalPath)'
- task: Docker@2
displayName: Login to container registry
inputs:
command: login
containerRegistry: '${{ parameters.releaseEndpoint }}'
- task: Bash@3
displayName: Build FraDrive container
inputs:
targetType: inline
script: |
cp docker/fradrive/Dockerfile .
docker build \
--tag $(buildImageUpstream)/fradrive:$(Build.BuildNumber) \
--tag $(buildImageUpstream)/fradrive:${{parameters.releaseTag}} \
--build-arg FROM_IMG=devfra.azurecr.io/de.fraport.trusted/ubuntu \
--build-arg FROM_TAG=20.04 \
--build-arg PROJECT_DIR=$(Build.Repository.LocalPath) \
--build-arg IN_CI=true \
--build-arg IN_CONTAINER=true \
--build-arg HTTPS_PROXY=http://proxy.frankfurt-airport.de:8080 \
--build-arg HTTP_PROXY=http://proxy.frankfurt-airport.de:8080 \
--build-arg NO_PROXY='localhost,127.0.0.1,*.docker.internal,*.azmk8s.io,devfra.azurecr.io,devfra.westeurope.data.azurecr.io' \
--build-arg FRAPORT_NOPROXY=dev.azure.com,*.dev.azure.com,*.fraport.de,*.frankfurt-airport.de \
.
- task: Docker@2
displayName: Push container to registry
inputs:
command: push
repository: 'de.fraport.fradrive.build/fradrive'
tags: '$(Build.BuildNumber),${{parameters.releaseTag}}'
- task: Docker@2
displayName: Logout from container registry
inputs:
command: logout
containerRegistry: '${{ parameters.releaseEndpoint }}'

View File

@ -1,61 +0,0 @@
# SPDX-FileCopyrightText: 2024-2025 Sarah Vaupel <sarah.vaupel@uniworx.de>
#
# SPDX-License-Identifier: AGPL-3.0-or-later
parameters:
- name: serviceName
type: string
- name: dependenciesCaches
type: object
default: []
- name: dependenciesBuildPool
type: string
default: 'Prod Private Agent Pool'
values:
- 'Prod Private Agent Pool'
- 'Prod Private Agent Pool DS2'
- 'Prod Private Agent Pool DS3'
- name: dependenciesBuildCores
type: number
default: 1
- name: dependenciesBuildTimeout
type: number
default: 60
jobs:
- job: SetupDependencies_${{parameters.serviceName}}
displayName: Install ${{parameters.serviceName}} dependencies
dependsOn: SetupImage_${{parameters.serviceName}}
${{ if eq(variables.setupImages, true) }}:
condition: succeeded()
${{ else }}:
condition: always()
pool: '${{parameters.dependenciesBuildPool}}'
timeoutInMinutes: ${{parameters.dependenciesBuildTimeout}}
container:
${{ if variables.setupImages }}:
image: $(buildImageUpstream)/${{parameters.serviceName}}:$(Build.BuildNumber)
${{ else }}:
image: $(buildImageUpstream)/${{parameters.serviceName}}:latest
endpoint: devfra
env:
PROJECT_DIR: $(Build.Repository.LocalPath)
IN_CONTAINER: true
IN_CI: true
steps:
# Restore previously-built dependencies from caches
- ${{ each cache in parameters.dependenciesCaches }}:
- template: ./../../steps/cache.yaml
parameters:
cacheIdent: '${{parameters.serviceName}}-dependencies'
cacheKeys: '${{cache.key}}'
cachePath: '${{cache.path}}'
# Compile dependencies
- template: ./../../steps/make.yaml
parameters:
makeJob: dependencies
makeService: ${{parameters.serviceName}}
makeVars: 'CPU_CORES=${{parameters.dependenciesBuildCores}} STACK_CORES=-j${{parameters.dependenciesBuildCores}}'
# (Note: a post-job for updating the dependency cache is automatically created, so no further step is due here.)

View File

@ -1,72 +0,0 @@
# SPDX-FileCopyrightText: 2024-2025 Sarah Vaupel <sarah.vaupel@uniworx.de>
#
# SPDX-License-Identifier: AGPL-3.0-or-later
parameters:
- name: imageName
type: string
- name: imageBase
type: object
jobs:
- job: SetupImage_${{parameters.imageName}}
displayName: Build ${{parameters.imageName}} image
condition: eq(variables.setupImages, true)
container:
image: devfra.azurecr.io/de.fraport.build/tools:1.1.0
endpoint: devfra
steps:
- task: Docker@2
displayName: Login to container registry
inputs:
command: login
containerRegistry: devfra
- task: Bash@3
displayName: Build ${{parameters.imageName}} image
inputs:
targetType: inline
script: |
cp docker/${{parameters.imageName}}/Dockerfile .
docker build \
--tag $(buildImageUpstream)/${{parameters.imageName}}:$(Build.BuildNumber) \
--build-arg FROM_IMG=${{parameters.imageBase.image}} \
--build-arg FROM_TAG=${{parameters.imageBase.tag}} \
--build-arg HTTPS_PROXY=http://proxy.frankfurt-airport.de:8080 \
--build-arg HTTP_PROXY=http://proxy.frankfurt-airport.de:8080 \
--build-arg NO_PROXY='localhost,127.0.0.1,*.docker.internal,*.azmk8s.io,devfra.azurecr.io,devfra.westeurope.data.azurecr.io' \
--build-arg FRAPORT_NOPROXY=dev.azure.com,*.dev.azure.com,*.fraport.de,*.frankfurt-airport.de \
--build-arg PROJECT_DIR=$(Build.Repository.LocalPath) \
--build-arg IN_CI=true \
--build-arg IN_CONTAINER=true \
.
- task: Bash@3
displayName: Push ${{parameters.imageName}} image
inputs:
targetType: inline
script: |
docker push $(buildImageUpstream)/${{parameters.imageName}}:$(Build.BuildNumber)
- task: Bash@3
displayName: Update latest ${{parameters.imageName}} image
condition: or(eq(variables.forcePushLatest, true), eq(variables['Build.SourceBranch'], 'refs/heads/master'))
inputs:
targetType: inline
script: |
docker tag $(buildImageUpstream)/${{parameters.imageName}}:$(Build.BuildNumber) $(buildImageUpstream)/${{parameters.imageName}}:latest
docker push $(buildImageUpstream)/${{parameters.imageName}}:latest
- task: Bash@3
displayName: Save image for publication
inputs:
targetType: inline
script: |
docker image save --output=$(Build.ArtifactStagingDirectory)/${{parameters.imageName}}.tar $(buildImageUpstream)/${{parameters.imageName}}:$(Build.BuildNumber)
- task: PublishBuildArtifacts@1
displayName: Publish image as artifact
inputs:
PathtoPublish: '$(Build.ArtifactStagingDirectory)'
ArtifactName: Image_${{parameters.imageName}}
publishLocation: 'Container'
- task: Docker@2
displayName: Logout from container registry
inputs:
command: logout
containerRegistry: devfra

View File

@ -1,141 +0,0 @@
# SPDX-FileCopyrightText: 2024-2025 Sarah Vaupel <sarah.vaupel@uniworx.de>
#
# SPDX-License-Identifier: AGPL-3.0-or-later
parameters:
- name: serviceName
type: string
default: serviceName
- name: serviceBase
type: object
default:
image: baseImage
tag: baseImageTag
- name: servicePool
type: string
default: 'Prod Private Agent Pool'
- name: serviceTimeout
type: number
default: 60
# extraBuildOptions: ''
- name: serviceDependsOn
type: object
default: []
- name: serviceRequiredArtifacts
type: object
default: []
- name: serviceArtifacts
type: string
default: ''
- name: buildSteps
type: object
stages:
- stage: ${{ parameters.serviceName }}
dependsOn: ${{ parameters.serviceDependsOn }}
pool: '${{ parameters.servicePool }}'
jobs:
- job: ImageBuild_${{parameters.serviceName}}
displayName: Build ${{parameters.serviceName}} image
condition: or(eq(variables.forcePushLatest, true), eq(variables.onMasterBranch, true), eq(variables.onUpdateBranch, true))
container:
image: devfra.azurecr.io/de.fraport.build/tools:1.1.0
endpoint: devfra
steps:
- checkout: self
- task: Docker@2
displayName: Login to container registry
inputs:
command: login
containerRegistry: devFra
- script: |
ls -a .
pwd
find .
- task: Bash@3
displayName: Build ${{parameters.serviceName}} image
inputs:
targetType: inline
script: |
cp docker/${{parameters.serviceName}}/Dockerfile .
docker build \
--tag $(buildImageUpstream)/${{parameters.serviceName}}:$(Build.BuildNumber) \
--build-arg FROM_IMG=${{parameters.serviceBase.image}} \
--build-arg FROM_TAG=${{parameters.serviceBase.tag}} \
--build-arg HTTPS_PROXY=http://proxy.frankfurt-airport.de:8080 \
--build-arg HTTP_PROXY=http://proxy.frankfurt-airport.de:8080 \
--build-arg NO_PROXY='localhost,127.0.0.1,*.docker.internal,*.azmk8s.io,devfra.azurecr.io,devfra.westeurope.data.azurecr.io' \
--build-arg FRAPORT_NOPROXY=dev.azure.com,*.dev.azure.com,*.fraport.de,*.frankfurt-airport.de \
--build-arg PROJECT_DIR=$(Build.Repository.LocalPath) \
--build-arg IN_CI=true \
--build-arg IN_CONTAINER=true \
.
- task: Bash@3
displayName: Push ${{ parameters.serviceName }} image
inputs:
targetType: inline
script: |
docker push $(buildImageUpstream)/${{parameters.serviceName}}:$(Build.BuildNumber)
- task: Bash@3
displayName: Update latest ${{parameters.serviceName}} image
condition: or(eq(variables.forcePushLatest, true), eq(variables.onMasterBranch, true))
inputs:
targetType: inline
script: |
docker tag $(buildImageUpstream)/${{parameters.serviceName}}:$(Build.BuildNumber) $(buildImageUpstream)/${{parameters.serviceName}}:latest
docker push $(buildImageUpstream)/${{parameters.serviceName}}:latest
- task: Docker@2
displayName: Logout from container registry
inputs:
command: logout
containerRegistry: devFra
- job: Build_${{parameters.serviceName}}
displayName: Build ${{parameters.serviceName}}
dependsOn:
- ImageBuild_${{parameters.serviceName}}
condition: in(dependencies.ImageBuild_${{parameters.serviceName}}.result, 'Succeeded', 'Skipped')
timeoutInMinutes: ${{ parameters.serviceTimeout }}
container:
# TODO: use BuildNumber instead of latest in update branches
# image: devfra.azurecr.io/de.fraport.fradrive.build/frontend:$(Build.BuildNumber)
image: $(buildImageUpstream)/${{parameters.serviceName}}:latest
endpoint: devfra
env:
PROJECT_DIR: $(Build.Repository.LocalPath)
IN_CONTAINER: true
IN_CI: true
steps:
- checkout: self
- ${{ each dependency in parameters.serviceRequiredArtifacts }}:
- task: DownloadPipelineArtifact@2
displayName: Download artifacts from ${{ dependency.name }} dependency
continueOnError: ${{ dependency.continueOnError }}
condition: ${{ dependency.condition }}
inputs:
artifactName: ${{ dependency.artifact }}
source: ${{ dependency.source }}
project: 'Fahrerausbildung'
pipeline: $(System.DefinitionId)
buildVersionToDownload: '${{ dependency.version }}'
tags: '${{ dependency.artifact }}'
allowPartiallySucceededBuilds: true
allowFailedBuilds: true
patterns: '${{ dependency.patterns }}'
targetPath: '$(Build.Repository.LocalPath)'
- ${{ each buildStep in parameters.buildSteps }}:
- template: ./service/build-step.yaml
parameters:
service: ${{ parameters.serviceName }}
buildStep: ${{ buildStep }}
- task: CopyFiles@2
displayName: Copy ${{parameters.serviceName}} artifacts
inputs:
Contents: ${{ parameters.serviceArtifacts }}
TargetFolder: '$(Build.ArtifactStagingDirectory)'
- task: PublishBuildArtifacts@1
displayName: Publish ${{parameters.serviceName}} artifacts
inputs:
PathtoPublish: '$(Build.ArtifactStagingDirectory)'
ArtifactName: '${{parameters.serviceName}}'
publishLocation: 'Container'

View File

@ -1,15 +0,0 @@
# SPDX-FileCopyrightText: 2025 Sarah Vaupel <sarah.vaupel@uniworx.de>
#
# SPDX-License-Identifier: AGPL-3.0-or-later
parameters:
- name: artifactName
type: string
steps:
- task: DownloadPipelineArtifact@2
displayName: Download artifacts from ${{parameters.artifactName}}
inputs:
source: 'current'
artifactName: '${{parameters.artifactName}}'
targetPath: '$(Build.Repository.LocalPath)'

View File

@ -1,18 +0,0 @@
# SPDX-FileCopyrightText: 2025 Sarah Vaupel <sarah.vaupel@uniworx.de>
#
# SPDX-License-Identifier: AGPL-3.0-or-later
parameters:
- name: cacheIdent
type: string
- name: cacheKeys
type: string
- name: cachePath
type: string
steps:
- task: Cache@2
displayName: Restore ${{parameters.cacheIdent}} cache
inputs:
key: '"${{parameters.cacheIdent}}" | ${{parameters.cacheKeys}}'
path: '${{parameters.cachePath}}'

View File

@ -1,35 +0,0 @@
# SPDX-FileCopyrightText: 2024-2025 Sarah Vaupel <sarah.vaupel@uniworx.de>
#
# SPDX-License-Identifier: AGPL-3.0-or-later
parameters:
- name: makeJob
type: string
values:
- dependencies
- compile
- lint
- test
- name: makeService
type: string
values:
- frontend
- backend
- name: makeVars
type: string
default: ''
steps:
- task: Bash@3
name: ${{parameters.makeJob}}_${{parameters.makeService}}
displayName: make ${{parameters.makeJob}}-${{parameters.makeService}}
env:
HTTPS_PROXY: http://proxy.frankfurt-airport.de:8080
HTTP_PROXY: http://proxy.frankfurt-airport.de:8080
NO_PROXY: 'localhost,127.0.0.1,*.docker.internal,*.azmk8s.io,devfra.azurecr.io,devfra.westeurope.data.azurecr.io'
FRAPORT_NOPROXY: 'dev.azure.com,*.dev.azure.com,*.fraport.de,*.frankfurt-airport.de'
PROJECT_DIR: $(Build.Repository.LocalPath)
inputs:
targetType: inline
script: |
make -- --${{parameters.makeJob}}-${{parameters.makeService}} IN_CONTAINER=true IN_CI=true PROJECT_DIR=${PROJECT_DIR} ${{parameters.makeVars}}

1
.gitignore vendored
View File

@ -37,7 +37,6 @@ uniworx.nix
.kateproject
src/Handler/Assist.bak
src/Handler/Course.SnapCustom.hs
frontend/src/env.sass
*.orig
/instance
.stack-work-*

49
utils/version.pl → .gitlab-ci/version.pl Normal file → Executable file
View File

@ -55,12 +55,12 @@ my %parKinds = (
},
autokind=>{
arity=>1,
def=>'release/prod=v,release/*=t,*=t',
def=>'main=v,master=v,test=t,*=t',
help=>'determine the tag kind from branch name instead of fixed value; use the first fitting glob',
},
change=>{
arity=>1,
def=>'chore=patch,feat=minor,feature=minor,fix=patch,BREAK=major,perf=patch,refactor=patch,test=patch,style=patch,revert=patch,docs=patch,build=patch,ci=patch',
def=>'chore=patch,feat=minor,feature=minor,fix=patch,BREAK=major,perf=patch,refactor=patch,test=patch,style=patch,revert=null,docs=patch,build=null,ci=null',
help=>'how to react on which commit type; can be partially given. Actions are: "null", "major", "minor", "patch" or state "invalid" for removing this type',
},
changelog=>{
@ -143,7 +143,6 @@ if($par{autokind}) {
my @rules = split /,/, $par{autokind};
RULES: {
for my $r(@rules) {
warn "$0: Processing autokind rule '$r'\n" if $par{v};
if($r!~m#(.*)=(.*)#) {
die "$0: Bad rule in autokind: $r\n";
}
@ -159,15 +158,14 @@ if($par{autokind}) {
$branchNameEscaped =~ s/[^0-9a-zA-Z]+/-/g;
if($par{'v'}) {
warn "VERBOSE: Parameters\n";
print "VERBOSE: Parameters\n";
for my $k(sort keys %par) {
warn " $k: $par{$k}\n"
print " $k: $par{$k}\n"
}
}
my %typeReact = ();
for my $as(split /,/, $par{change}) {
warn "$0: processing change parameter '$as'\n" if $par{v};
if($as=~m#(.*)=(.*)#) {
$typeReact{$1} = $2;
} else {
@ -246,21 +244,16 @@ sub parseVersion {
warn "$0: unexpected old version number: $v\n" if $par{v};
return undef
}
$cap{pre} = 'v' if '' eq $cap{pre};
my %ret = (
prefix=>$cap{pre},
major=>$cap{ma},
minor=>$cap{mi},
patch=>$cap{p},
subpatch=>$cap{sp},
branchname=>$cap{brn},
branchversion=>$cap{brv},
);
if($par{v}) {
my $parsed = join '; ', map { "$_=>".($ret{$_}//'') } sort keys %ret;
warn "Version '$v' was parsed to '$parsed'\n"
$pre = 'v' if '' eq $pre;
return {
prefix=>$pre,
major=>$ma,
minor=>$mi,
patch=>$p,
subpatch=>$sp,
branchname=>$brn,
branchversion=>$brv,
}
return \%ret
}
#@oldVersions = sort {
@ -300,7 +293,7 @@ sub vsCompare {
($v->{minor} // 0) <=> ($w->{minor} // 0) ||
($v->{patch} // 0) <=> ($w->{patch} // 0) ||
($v->{branchname} // '') cmp ($w->{branchname} // '') ||
($v->{branchversion} // 0) <=> ($w->{branchversion} // 0) ||
($v->{branchversion} // '') <=> ($w->{branchversion} // '') ||
($v->{subpatch} // '') cmp ($w->{subpatch} // '')
)
} elsif($v->{prefix}=~m/^v?$/ and !$w->{prefix}=~m/^v?$/) {
@ -376,7 +369,6 @@ if('-' eq $par{vcslog}) {
}
my @versions = ();
for my $v(@versionsOrig) {
warn "$0: Processing orig version (part 1): '$v'\n" if $par{v};
if($v=~m#^(.*?\S)\s*::::\s*(.*?)\s*::::\s*(.*)#) {
push @versions, {
hash => $1,
@ -394,7 +386,6 @@ my $tag = undef;
my @versionPast = ();
VERSION: for my $v(@versions) {
warn "$0: Processing version (part 2): $v\n" if $par{v};
#if($v->{meta}=~m#tag\s*:\s*\Q$par{kind}\E(.*)\)#) {
# $tag=$1;
# last VERSION
@ -424,7 +415,6 @@ VERSION: for my $v(@versions) {
#$tag = parseVersion($tag);
for my $r(reverse @change) {
warn "$0: Processing change: $r\n" if $par{v};
if('major' eq $r->{react}) {
$tag->{major}++;
$tag->{minor}=0;
@ -474,7 +464,6 @@ my $highStart = $mainVersion ? $sortAll[0] : $sortSee[0];
my $highSee = $sortSee[0];
my %reactCollect = ();
SEARCHVERSION: for my $v(@versions) {
warn "$0: search for version: '$v'\n" if $par{v};
next unless $v->{version};
next unless $v->{react};
$reactCollect{$v->{react}} = 1;
@ -486,12 +475,10 @@ SEARCHVERSION: for my $v(@versions) {
sub justVersionInc {
my ($v, $react) = @_;
my $vv = parseVersion($v);
$vv->{patch}++; # if $react->{patch}; # in principal a good idea to increase only when a patch action happend, but we need a new version, even if nothing happend, so we always increase patch; if there are other changes as well, it is overwritten anyways
$vv->{patch}++ if $react->{patch};
do {$vv->{minor}++; $vv->{patch}=0} if $react->{minor};
do {$vv->{major}++; $vv->{minor}=0; $vv->{patch}=0} if $react->{major};
my $ret = vsJustVersion($vv);
warn "$0: version inc from '$v' to $ret\n" if $par{v};
return $ret
return vsJustVersion($vv);
}
my $newVersion = undef;
@ -514,7 +501,6 @@ for(@allVersions) {
$allVersions{$_} = 1
}
while(exists $allVersions{$newVersion}) {
warn "$0: Version conflict, so we try another version, '$newVersion' exists already\n" if $par{v};
if($mainVersion) {
die "$0: probably internal error (collision in main version)\n"
}
@ -544,7 +530,6 @@ if($par{changelog}) {
my %seen = ();
my @sects = ([]);
for(@changelog) {
warn "$0: Changelog processing: '$_'\n" if $par{v};
push @sects, [] if m/^## /;
push @{$sects[-1]}, $_;
if(m#/commit/([a-f0-9]+)\s*\)\s*\)\s*$#) {
@ -558,7 +543,6 @@ if($par{changelog}) {
shift @sects;
}
for my $s(@sects) {
warn "$0: Changelog processing, section search: '$s'\n" if $par{v};
my $hh = $s->[0];
chomp $hh;
my $cnt = @$s;
@ -583,7 +567,6 @@ if($par{changelog}) {
'feature' => 'Features',
);
SELECTCHANGELOG: for my $v(@versions) {
warn "$0: Changelog processing, version selection: '$v'\n" if $par{v};
last SELECTCHANGELOG if $seen{$v->{hash}};
next unless $v->{subject}=~m#^\s*([a-z]+)\s*(!?)\s*((?:\(.*?\))?)\s*:\s*(.*?)\s*$#i;
my ($kind, $break, $context, $msg) = ($1, $2, $3, $4);

View File

@ -7,33 +7,33 @@ const standardVersionUpdaterYaml = require.resolve('standard-version-updater-yam
module.exports = {
scripts: {
// postbump: './sync-versions.hs && git add -- package.yaml', // moved to bumpFiles
postchangelog: 'sed \'s/^### \\[/## [/g\' -i CHANGELOG.md',
postchangelog: 'sed \'s/^### \\[/## [/g\' -i CHANGELOG.md'
},
packageFiles: ['package.json', 'package.yaml'],
bumpFiles: [
{
filename: 'package.json',
type: 'json',
type: 'json'
},
{
filename: 'package-lock.json',
type: 'json',
type: 'json'
},
{
filename: 'package.yaml',
updater: standardVersionUpdaterYaml,
updater: standardVersionUpdaterYaml
},
{
filename: 'nix/docker/version.json',
type: 'json',
type: 'json'
},
{
filename: 'nix/docker/demo-version.json',
type: 'json',
},
type: 'json'
}
],
commitUrlFormat: 'https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/{{hash}}',
compareUrlFormat: 'https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/{{previousTag}}...{{currentTag}}',
issueUrlFormat: 'https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/issues/{{id}}',
userUrlFormat: 'https://gitlab2.rz.ifi.lmu.de/{{user}}',
userUrlFormat: 'https://gitlab2.rz.ifi.lmu.de/{{user}}'
};

View File

@ -16,48 +16,6 @@ All notable changes to this project will be documented in this file. See [standa
## [v27.4.59-test-f0.0.14](https://fraport@dev.azure.com/fraport/Fahrerausbildung/_git/FRADrive//compare/v27.4.59-test-e0.0.14...v27.4.59-test-f0.0.14) (2025-02-14)
## [v27.4.59-test-e0.0.14](https://fraport@dev.azure.com/fraport/Fahrerausbildung/_git/FRADrive//compare/v27.4.59-test-e0.0.13...v27.4.59-test-e0.0.14) (2025-02-13)
## [v27.4.59-test-e0.0.13](https://fraport@dev.azure.com/fraport/Fahrerausbildung/_git/FRADrive//compare/v27.4.59-test-e0.0.12...v27.4.59-test-e0.0.13) (2025-02-12)
## [v27.4.59-test-e0.0.12](https://fraport@dev.azure.com/fraport/Fahrerausbildung/_git/FRADrive//compare/v27.4.59-test-d0.0.12...v27.4.59-test-e0.0.12) (2025-02-12)
## [v27.4.59-test-d0.0.12](https://fraport@dev.azure.com/fraport/Fahrerausbildung/_git/FRADrive//compare/v27.4.59-test-d0.0.11...v27.4.59-test-d0.0.12) (2025-02-11)
## [v27.4.59-test-d0.0.11](https://fraport@dev.azure.com/fraport/Fahrerausbildung/_git/FRADrive//compare/v27.4.59-test-c0.0.11...v27.4.59-test-d0.0.11) (2025-02-11)
## [v27.4.59-test-c0.0.11](https://fraport@dev.azure.com/fraport/Fahrerausbildung/_git/FRADrive//compare/v27.4.59-test-b0.0.11...v27.4.59-test-c0.0.11) (2025-02-11)
## [v27.4.59-test-b0.0.11](https://fraport@dev.azure.com/fraport/Fahrerausbildung/_git/FRADrive//compare/v27.4.59-test-c0.0.10...v27.4.59-test-b0.0.11) (2025-02-11)
## [v27.4.59-test-c0.0.10](https://fraport@dev.azure.com/fraport/Fahrerausbildung/_git/FRADrive//compare/v27.4.59-test-b0.0.10...v27.4.59-test-c0.0.10) (2025-02-11)
## [v27.4.59-test-b0.0.10](https://fraport@dev.azure.com/fraport/Fahrerausbildung/_git/FRADrive//compare/v27.4.59-test-a0.0.10...v27.4.59-test-b0.0.10) (2025-02-11)
## [v27.4.59-test-a0.0.10](https://fraport@dev.azure.com/fraport/Fahrerausbildung/_git/FRADrive//compare/v27.4.59-test-a0.0.9...v27.4.59-test-a0.0.10) (2025-02-11)
## [v27.4.59-test-a0.0.9](https://fraport@dev.azure.com/fraport/Fahrerausbildung/_git/FRADrive//compare/v27.4.59-test-a0.0.8...v27.4.59-test-a0.0.9) (2025-02-10)
## [v27.4.59-test-a0.0.8](https://fraport@dev.azure.com/fraport/Fahrerausbildung/_git/FRADrive//compare/v27.4.59-test-a0.0.7...v27.4.59-test-a0.0.8) (2025-02-10)
## [v27.4.59-test-a0.0.7](https://fraport@dev.azure.com/fraport/Fahrerausbildung/_git/FRADrive//compare/v27.4.59-test-a0.0.6...v27.4.59-test-a0.0.7) (2025-02-10)
## [v27.4.59-test-a0.0.6](https://fraport@dev.azure.com/fraport/Fahrerausbildung/_git/FRADrive//compare/v27.4.59-test-a0.0.5...v27.4.59-test-a0.0.6) (2025-02-08)
## [v27.4.59-test-a0.0.5](https://fraport@dev.azure.com/fraport/Fahrerausbildung/_git/FRADrive//compare/v27.4.59-test-a0.0.4...v27.4.59-test-a0.0.5) (2025-02-07)
## [v27.4.59-test-a0.0.4](https://fraport@dev.azure.com/fraport/Fahrerausbildung/_git/FRADrive//compare/v27.4.59-test-a0.0.3...v27.4.59-test-a0.0.4) (2025-02-07)
## [v27.4.59-test-a0.0.3](https://fraport@dev.azure.com/fraport/Fahrerausbildung/_git/FRADrive//compare/v27.4.59-test-a0.0.2...v27.4.59-test-a0.0.3) (2025-02-06)
## [v27.4.59-test-a0.0.2](https://fraport@dev.azure.com/fraport/Fahrerausbildung/_git/FRADrive//compare/v27.4.59-test-a0.0.1...v27.4.59-test-a0.0.2) (2025-02-05)
## [v27.4.59-test-a0.0.1](https://fraport@dev.azure.com/fraport/Fahrerausbildung/_git/FRADrive//compare/v27.4.59-test-a0.0.0...v27.4.59-test-a0.0.1) (2025-02-05)
### Bug Fixes
* **ghci:** ghci works now as expected ([c3117db](https://fraport@dev.azure.com/fraport/Fahrerausbildung/_git/FRADrive/commit/c3117dbdcd1de9ef9f0751afa45018e2ebce2c42))
## [v27.4.59-test-a0.0.0](https://fraport@dev.azure.com/fraport/Fahrerausbildung/_git/FRADrive//compare/v27.4.59...v27.4.59-test-a0.0.0) (2024-10-25)
### Features
@ -65,6 +23,97 @@ All notable changes to this project will be documented in this file. See [standa
* **util script:** Util script for renaming of files added. ([caf8fec](https://fraport@dev.azure.com/fraport/Fahrerausbildung/_git/FRADrive/commit/caf8fec5acb94df16293bf9aa0cdab766f8829e8))
* **frontend:** load icons from svg files ([22781e1](https://fraport@dev.azure.com/fraport/Fahrerausbildung/_git/FRADrive/commit/22781e1565e890cf6c5b40973146b0334cb667aa))
### Bug Fixes
* **stack.yaml:** move to uniworx.de gitlab ([55484e6](https://fraport@dev.azure.com/fraport/Fahrerausbildung/_git/FRADrive/commit/55484e631b786ea3710d322282019baf5292c243))
* **utils/renamer:** Mehr outputs nur im verbose-Fall. ([ac30cb9](https://fraport@dev.azure.com/fraport/Fahrerausbildung/_git/FRADrive/commit/ac30cb9e6712d0ee3f204da4863d1e2509af8a76))
* **utils:** Verboseparameter -v hinzugefuegt; rekursives makedir; genauere Meldungen. ([1806d9f](https://fraport@dev.azure.com/fraport/Fahrerausbildung/_git/FRADrive/commit/1806d9f01fc4a0746d2f9df42ef1ee6827c7fa09))
* **Dockerfile:** change rights of source dir to env user ([e7a8183](https://fraport@dev.azure.com/fraport/Fahrerausbildung/_git/FRADrive/commit/e7a8183656ae419cfee2942543045c6fa6a9caa3))
* **Makefile:** add missing dependency on well-known for backend-builds ([a09dc59](https://fraport@dev.azure.com/fraport/Fahrerausbildung/_git/FRADrive/commit/a09dc59f260843f8815c382576bb5254d21104bf))
* **frontend:** fixed icon colour in table headers ([4c4571d](https://fraport@dev.azure.com/fraport/Fahrerausbildung/_git/FRADrive/commit/4c4571d2d0879e89f2572eba6015d34a7f4794c8))
* **doc:** minor haddock problems ([d4f8a6c](https://fraport@dev.azure.com/fraport/Fahrerausbildung/_git/FRADrive/commit/d4f8a6c77b2a4a4540935f7f0beca0d0605508c8))
## [27.4.76](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v27.4.75...v27.4.76) (2024-08-08)
### Bug Fixes
* **ap:** disambiguate action message ([8b0466e](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/8b0466e74e36e1d0d07518fd317d46b00ab53eff))
* **avs:** fix [#173](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/issues/173) by not using firm superior email as display email ([43f5c5f](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/43f5c5f4854d1ab2af27b479e72a58e2818a5696))
* **avs:** towards [#117](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/issues/117) update if current value is Nothing even if oldval == newval ([d1fa01f](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/d1fa01fcc5125c4adee8849f9c944884926f78ad))
* **avs:** using firm superior as UserEmail is a no-go due to uniqueness constraints ([507a7e0](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/507a7e02fc68476d01031dc9f9ee1a669a453ed1))
* **build:** linter likes it ([f929e03](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/f929e03129378e08c8a08ed4bd6f8e8716401813))
* **course:** fix [#150](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/issues/150) course edit for associated qualifications requires school admin or lecturer rights ([5b6e4e6](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/5b6e4e60e7d2957fbce93ee2e2d6d3464b4e3db7))
* **course:** fix [#148](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/issues/148) course qualification ordering ([cfd2534](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/cfd25348ad3b63ac6bc5031467a3c4ead2e07eed)), closes [#150](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/issues/150)
* **course:** fix [#149](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/issues/149) course cloning proposes associated qualifications ([e141976](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/e1419766f3a06f702abad0ea42f6552305504ba0))
* **course:** fix [#150](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/issues/150) no longer allow duplicated associated qualifications and orders due to editing existing ([ec02767](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/ec027675525b30198378745ed281f60a42471807))
* **course:** WIP course cloning should propose same associated qualifications, towards [#149](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/issues/149) ([bc47387](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/bc47387c91dda60a2f12e52dba28ea7b079316f0))
* **lms:** max e-learning tries default removed and info added to lms overview ([11fdcf0](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/11fdcf0d445b8cfe97c3a3c26513a9229937c536))
* **user:** format userDisplayNames having umlaut substitutes with respect to userSurname correctly ([e35a5e9](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/e35a5e99a6cea0976fd1c28f919e7d0ac0338503))
## [27.4.75](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v27.4.74...v27.4.75) (2024-07-12)
### Bug Fixes
* **build:** make linter happy again ([c17c18f](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/c17c18f9247ef322bc051602a3cb4a52cd50affa))
* **build:** minor ([ab28c8c](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/ab28c8c2437680023d80e6ab43113d4328b3a151))
* **firm:** fix [#157](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/issues/157) by removing redundant duplicated code in firm user and supervision handling ([28e2739](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/28e2739e515700d15c75647c0efe2fe9a9cf15b1))
* **job:** change some queueJob' to queueJob instead ([fa0541a](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/fa0541aa4eaf10f98535a0959593b148b8346109))
* **lms:** allow 2nd reminders to be independent of renewal period ([d853e85](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/d853e8559b753865ee818bf24764f5c8d2e2303f))
* **lms:** move lms reuse info from QualificationR to LmsR ([468af9d](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/468af9de9da44a8ad685ca4bb6890a3e630b58be))
* **lms:** send second reminder indepentently from renewal period ([a97c3a5](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/a97c3a5c9d3cb9dddf90f561712f0845400893bd))
* **nix:** workaround parsing port numbers failed in nix-shell ([b5215cc](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/b5215cc7e8df3a7ad636271c8e6950979b2b8e42))
* **users:** nameHtml no longer complains about differing case for surname and displayname ([a1668f8](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/a1668f891a36b887439afb098f016ef22535af42))
* **users:** remove users with company post address from list of unreachable users ([c813c66](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/c813c665ed306135b7813d91d23310341c689f41))
## [27.4.74](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v27.4.73...v27.4.74) (2024-07-04)
### Bug Fixes
* **lms:** fix [#161](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/issues/161) lms for multiple joint qualifications ([f869a82](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/f869a829d2c1a726930864b3af62d1f0fbebe955))
## [27.4.73](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v27.4.72...v27.4.73) (2024-07-03)
### Bug Fixes
* **letter:** rephrase some minor letter parts ([0ac75e0](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/0ac75e0d5948cb90855d0e36ca8e99c22a0f6fcb))
## [27.4.72](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v27.4.71...v27.4.72) (2024-07-02)
### Bug Fixes
* **avs:** do not associate users by AvsInfoPersonEmail ([9e2f221](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/9e2f2214ce5c7ee1e8d80e6fa75298b7a70d9043))
* **avs:** fix superfluous quotes for matriculation numbers on newly created users ([ff9014c](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/ff9014ce05d197c1dc0fce0774a640789cb38b26))
* **avs:** towards [#169](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/issues/169) - superiors are elevated to max priority for that company ([5bf8539](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/5bf85394d4db6de8f10b4e318d667130d37601ac))
* **firm:** supervisor secondary did not work as intended ([d4f3ce7](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/d4f3ce7bf3d208b16f95ab81971b47dfa752939a))
## [27.4.71](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v27.4.70...v27.4.71) (2024-06-27)
### Bug Fixes
* **avs:** company superior emails become company wide supervisors ([37efc89](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/37efc89e0723452e6d271ba5b43d6bd026642190))
* **avs:** match mobile number better between LDAP and AVS ([f108c6c](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/f108c6cfec2d94d866e7c1605b0abe5471fd0f2b))
* **avs:** new AVS from existing LDAP user no longer misses fields ([2559346](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/2559346d963ede802321dfc8cbd2088d9a5de685))
* **avs:** priority for picking primary email demote superior ([e4fa1dd](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/e4fa1ddd6873910bef82d569fe16aca936efc567))
* **build:** add missing license file ([8721bdb](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/8721bdb3f349658baab144d64c19942bfd7fa49a))
* **build:** hlint wants a newtype instead ([18cdc52](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/18cdc52df094b9dbccd4f015561367cea59e33fe))
* **doc:** fix erroneous unintentional haddock annotations ([3dfc7f8](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/3dfc7f8c8b12dd6ef87848a75f1669d700fffe4c))
* **i18n:** add missing translation for new primary company ([c212f2e](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/c212f2e8d735616e59c9b8111a34118e3a48fd47))
* **i18n:** add missing translation for new primary company ([2cc529b](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/2cc529be39655c317ca028f8f09fa80826ec668d))
* **ldap:** match mobile number better between LDAP and AVS ([47e5628](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/47e56280fce4ad37e6bc3b9f1c61cb7867069cc5))
* **letter:** adjust spacing, pin location and interpolation ([d4a0e1f](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/d4a0e1f201151f76e8e9afd67b456cc878d2afde))
* **letter:** convenience links working again ([5f1af13](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/5f1af130edae7ada2f0c7f7829890bbe0d4f395a))
* **letter:** expiry and valid dates were wrong ([f8c3663](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/f8c36636ff1f2591507e993af32ed01af94cf1fc))
* **letter:** switch markdown for renewal letter too ([c38e87e](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/c38e87e1e0e9285a10c00521b7440cd8246af88a))
* **print:** fix [#167](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/issues/167) by sotring affected user in PrintJob ([73aecc2](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/73aecc2df833bdeed93a113b6c756e36b50491b7))
## [27.4.70](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v27.4.69...v27.4.70) (2024-06-21)
### Bug Fixes
* **stack.yaml:** move to uniworx.de gitlab ([55484e6](https://fraport@dev.azure.com/fraport/Fahrerausbildung/_git/FRADrive/commit/55484e631b786ea3710d322282019baf5292c243))

View File

@ -22,16 +22,16 @@ export CONTAINER_FILE
export CONTAINER_IDENT
export CF_PREFIX
export DEVELOP
export MOUNT_DIR=/mnt/fradrive
export CONTAINER_ATTACHED
export CONTAINER_INIT
export CONTAINER_CLEANUP
export PROJECT_DIR=/fradrive
export SERVICE
export SERVICE_VARIANT ?= $(SERVICE)
export JOB
export IMAGE
export SET_IMAGE
export CONTAINER_CMD
export SET_CONTAINER_CMD
export ENTRYPOINT
export EXEC_OPTS
@ -65,7 +65,7 @@ help:
# HELP: stop all running containers and remove all compilation results in the directory (but leave images including dependencies unharmed)
clean:
rm -rf develop
-rm -rf node_modules .npm .cache assets/icons assets/favicons static well-known config/manifest.json frontend/src/env.sass
-rm -rf node_modules .npm .cache assets/icons assets/favicons static well-known config/manifest.json
-rm -rf .stack-work .stack-work.lock
-rm -rf bin .Dockerfile develop
-$(CONTAINER_COMMAND) container prune --force
@ -84,7 +84,6 @@ clean-all: clean-images
.PHONY: release
# HELP: create, commit and push a new release
# TODO: only release when build and tests are passing!!!
release:
VERSION=`./utils/version.pl -changelog CHANGELOG.md -v` ; \
git add CHANGELOG.md ; \
@ -110,24 +109,24 @@ start:
.PHONY: %-backend
%-backend: SERVICE=backend
%-backend: SERVICE_VARIANT=backend
%-backend: IMAGE=localhost/fradrive/backend
%-backend: CONTAINER_CMD=localhost/fradrive/backend
%-backend: BASE_PORTS = "DEV_PORT_HTTP=3000" "DEV_PORT_HTTPS=3443"
.PHONY: %-uniworxdb
%-uniworxdb: SERVICE=backend
%-uniworxdb: SERVICE_VARIANT=uniworxdb
%-uniworxdb: IMAGE=localhost/fradrive/backend
%-uniworxdb: CONTAINER_CMD=localhost/fradrive/backend
.PHONY: %-ghci
%-ghci: SERVICE=backend
%-ghci: SERVICE_VARIANT=ghci
%-ghci: IMAGE=localhost/fradrive/backend
%-ghci: CONTAINER_CMD=localhost/fradrive/backend
.PHONY: %-hoogle
%-hoogle: SERVICE=backend
%-hoogle: SERVICE_VARIANT=hoogle
%-hoogle: BASE_PORTS = "HOOGLE_PORT=8081"
%-hoogle: IMAGE=localhost/fradrive/backend
%-hoogle: CONTAINER_CMD=localhost/fradrive/backend
--start-hoogle:
HOOGLE_PORT=`cat $(CONTAINER_FILE) | grep 'HOOGLE_PORT=' | sed 's/HOOGLE_PORT=//'` ; \
stack $(STACK_CORES) hoogle -- server --local --port $${HOOGLE_PORT}
@ -135,24 +134,24 @@ start:
.PHONY: %-frontend
%-frontend: SERVICE=frontend
%-frontend: SERVICE_VARIANT=frontend
%-frontend: IMAGE=localhost/fradrive/frontend
%-frontend: CONTAINER_CMD=localhost/fradrive/frontend
.PHONY: %-postgres
%-postgres: SERVICE=postgres
%-postgres: SERVICE_VARIANT=postgres
%-postgres: BASE_PORTS = "PGPORT=5432"
%-postgres: IMAGE=localhost/fradrive/postgres
%-postgres: CONTAINER_CMD=localhost/fradrive/postgres
.PHONY: %-memcached
%-memcached: SERVICE=memcached
%-memcached: SERVICE_VARIANT=memcached
%-memcached: SET_IMAGE=$$(MEMCACHED_IMAGE) --port=`cat $$(CONTAINER_FILE) | grep 'MEMCACHED_PORT=' | sed 's/MEMCACHED_PORT=//'`
%-memcached: SET_CONTAINER_CMD=$$(MEMCACHED_IMAGE) --port=`cat $$(CONTAINER_FILE) | grep 'MEMCACHED_PORT=' | sed 's/MEMCACHED_PORT=//'`
%-memcached: BASE_PORTS = "MEMCACHED_PORT=11211"
.PHONY: %-minio
%-minio: SERVICE=minio
%-minio: SERVICE_VARIANT=minio
%-minio: SET_IMAGE=$$(MINIO_IMAGE) -- server `mktemp` --address=:`cat $$(CONTAINER_FILE) | grep 'UPLOAD_S3_PORT=' | sed 's/UPLOAD_S3_PORT=//'`
%-minio: SET_CONTAINER_CMD=$$(MINIO_IMAGE) -- server `mktemp` --address=:`cat $$(CONTAINER_FILE) | grep 'UPLOAD_S3_PORT=' | sed 's/UPLOAD_S3_PORT=//'`
%-minio: BASE_PORTS = "UPLOAD_S3_PORT=9000"
.PHONY: start-%
@ -214,13 +213,18 @@ ghci: shell-ghci;
rebuild-%:
$(MAKE) -- --image-build SERVICE=$* NO_CACHE=--no-cache
--image-build:
ifeq "$(IMAGE)" "localhost/fradrive/$(SERVICE)"
ifeq "$(CONTAINER_CMD)" "localhost/fradrive/$(SERVICE)"
rm -f .Dockerfile
ln -s docker/$(SERVICE)/Dockerfile .Dockerfile
PROJECT_DIR=/fradrive; \
MOUNT_DIR=/mnt/fradrive; \
PROJECT_DIR=/mnt/fradrive; \
if [ "$(IN_CI)" == "true" ] ; then \
PROJECT_DIR=/fradrive; \
fi; \
if [ "$(IN_CONTAINER)" == "false" ] ; then \
$(CONTAINER_COMMAND) build $(NO_CACHE) \
-v $(PWD):$${PROJECT_DIR}:rw \
-v $(PWD):$${MOUNT_DIR} \
--build-arg MOUNT_DIR=$(MOUNT_DIR) \
--build-arg PROJECT_DIR=$${PROJECT_DIR} \
--env IN_CONTAINER=true \
--env JOB=$(JOB) \
@ -235,22 +239,22 @@ endif
DEVELOP=`cat develop/.current` ; \
./utils/watchcontainerrun.sh "$(CONTAINER_COMMAND)" "$(CONTAINER_FILE)" "$(CONTAINER_INIT)" "$(CONTAINER_CLEANUP)" & \
CONTAINER_NAME=fradrive.$(CURR_DEV).$(CONTAINER_IDENT) ; \
if ! [ -z "$(SET_IMAGE)" ] ; \
if ! [ -z "$(SET_CONTAINER_CMD)" ] ; \
then \
IMAGE="$(SET_IMAGE)" ; \
CONTAINER_CMD="$(SET_CONTAINER_CMD)" ; \
else \
IMAGE=$(IMAGE) ; \
CONTAINER_CMD=$(CONTAINER_CMD) ; \
fi ; \
CONTAINER_ID=`$(CONTAINER_BGRUN) \
-v $(PWD):$(PROJECT_DIR):rw \
-v $(PWD):$(MOUNT_DIR) \
--env IN_CONTAINER=true \
--env FRADRIVE_MAKE_TARGET="--$(JOB)-$(SERVICE_VARIANT)" \
--env CONTAINER_FILE=$(CONTAINER_FILE) \
--env CONTAINER_NAME=$${CONTAINER_NAME} \
--env JOB=$(JOB) \
--env SRC=$(SRC) \
--name $${CONTAINER_NAME} \
$${IMAGE} \
make -- --$(JOB)-$(SERVICE_VARIANT) IN_CONTAINER=true \
$${CONTAINER_CMD} \
` ; \
printf "CONTAINER_ID=$${CONTAINER_ID}" >> "$(CONTAINER_FILE)" ; \
if [[ "true" == "$(CONTAINER_ATTACHED)" ]] ; then \
@ -258,6 +262,7 @@ endif
fi
# For Reverse Proxy Problem see: https://groups.google.com/g/yesodweb/c/2EO53kSOuy0/m/Lw6tq2VYat4J
# HELP(start-backend): start development instance
--start-backend:
export YESOD_IP_FROM_HEADER=true; \
@ -282,23 +287,22 @@ endif
--compile-backend:
stack build $(STACK_CORES) --fast --profile --library-profiling --executable-profiling --flag uniworx:-library-only $(--DEVELOPMENT) --local-bin-path $$(pwd)/bin --copy-bins
# HELP(dependencies-backend): (re-)build backend dependencies
--dependencies-backend: #uniworx.cabal
chown -R `id -un`:`id -gn` "$(PROJECT_DIR)"; \
stack build -j2 --only-dependencies
--dependencies-backend: uniworx.cabal
stack build $(STACK_CORES) --fast --only-dependencies
# HELP(lint-backend): lint backend
--lint-backend:
stack build $(STACK_CORES) --test --fast --flag uniworx:library-only $(--DEVELOPMENT) uniworx:test:hlint
# HELP(test-backend): test backend
--test-backend:
stack build $(STACK_CORES) --test --coverage --fast --flag uniworx:library-only $(--DEVELOPMENT)
# uniworx.cabal:
# stack exec -- hpack --force
uniworx.cabal:
stack exec -- hpack --force
# HELP(compile-frontend): compile frontend assets
--compile-frontend: node_modules assets esbuild.config.mjs frontend/src/env.sass
--compile-frontend: node_modules assets esbuild.config.mjs
npm run build
--start-frontend: --compile-frontend;
--dependencies-frontend: node_modules assets;
--dependencies-frontend: node_modules assets static well-known;
node_modules: package.json package-lock.json
npm install --cache .npm --prefer-offline
package-lock.json: package.json
@ -310,15 +314,9 @@ assets/icons: node_modules assets/icons-src/fontawesome.json
./utils/renamer.pl node_modules/@fortawesome/fontawesome-free/svgs/solid assets/icons-src/fontawesome.json assets/icons/fradrive
./utils/renamer.pl node_modules/@fortawesome/fontawesome-free/svgs/regular assets/icons-src/fontawesome.json assets/icons/fradrive
-cp assets/icons-src/*.svg assets/icons/fradrive
frontend/src/env.sass:
echo "\$$path: '$${PROJECT_DIR}'" > frontend/src/env.sass
static: node_modules assets esbuild.config.mjs frontend/src/env.sass
static: node_modules assets esbuild.config.mjs
npm run build
well-known: static;
--lint-frontend: --compile-frontend
npm run lint
--test-frontend: --compile-frontend
npm run test
# HELP(compile-uniworxdb): clear and fill database. requires running postgres instance (use "make start-postgres" to start one)
# TODO (db-m-$MIGRATION-backend): apply migration (see src/Model/Migration/Definition.hs for list of available migrations)
@ -327,7 +325,6 @@ well-known: static;
AVSPASS=${AVSPASS:-nopasswordset} ; \
./bin/uniworxdb $(UNIWORXDB_OPTS)
# HELP(shell-ghci): enter ghci shell. Use "make ghci SRC=<MODULE_FILE.hs>" to load specific source modules."
--shell-ghci:
stack ghci -- $(SRC)
# --main-is uniworx:exe:uniworx

View File

@ -29,6 +29,7 @@
"file-upload": "file-arrow-up",
"file-zip": "file-zipper",
"file-csv": "file-csv",
"file-missing": "file-circle-minus",
"sft-question": "circle-question",
"sft-hint": "life-ring",
"sft-solution": "circle-exclamation",
@ -76,12 +77,13 @@
"submission-no-users": "user-slash",
"reset": "arrow-rotate-left",
"blocked": "ban",
"certificate": "certificate",
"certificate": "car-side",
"print-center": "envelopes-bulk",
"letter": "envelopes-bulk",
"at": "at",
"supervisor": "person",
"supervisor-foreign": "person-rays",
"superior": "user-tie",
"waiting-for-user": "user-gear",
"expired": "hourglass-end",
"locked": "lock",
@ -89,9 +91,18 @@
"trash": "trash",
"reset-tries": "trash-can-arrow-up",
"company": "building",
"company-warning": "building-circle-exclamation",
"edit": "pen-to-square",
"user-edit": "user-pen",
"loading": "spinner",
"placeholder": "notdef"
"placeholder": "notdef",
"reroute": "diamond-turn-right",
"top": "award",
"wildcard": "asterisk",
"user-unknown": "user-slash",
"user-badge": "id-badge",
"glasses": "glasses",
"missing": "question",
"pin-protect": "key"
}

254
azure-pipelines.yaml Executable file → Normal file
View File

@ -1,197 +1,67 @@
# SPDX-FileCopyrightText: 2024-2025 Sarah Vaupel <sarah.vaupel@uniworx.de>
# SPDX-FileCopyrightText: 2024 Sarah Vaupel <sarah.vaupel@uniworx.de>
#
# SPDX-License-Identifier: AGPL-3.0-or-later
trigger:
branches:
include:
- '*'
tags:
include:
- '*'
#paths:
# exclude:
# - CHANGELOG.md
parameters:
- name: services
type: object
default:
- name: frontend
imageBase:
image: devfra.azurecr.io/de.fraport.build/npm
tag: node-20
# extraBuildOptions: |
# --build-arg NPM_CUSTOM_REGISTRY=https://pkgs.dev.azure.com/fraport/_packaging/packages/npm/registry/
dependsOn: []
dependenciesCaches:
- key: package.json | package-lock.json
path: node_modules/
- key: package.json | package-lock.json
path: .npm/
- key: package.json | esbuild.config.mjs | utils/renamer.pl | utils/faviconize.pl | frontend/src/icons.scss
path: assets/icons/
- key: package.json | esbuild.config.mjs | utils/renamer.pl | utils/faviconize.pl | frontend/src/icons.scss
path: assets/favicons/
buildPool: 'Prod Private Agent Pool'
buildCores: 1
buildTimeout: 60
buildArtifacts: |
assets/icons/fradrive/*.svg
assets/favicons/*.png
assets/favicons/include.html
frontend/src/env.sass
config/manifest.json
static/**/*
well-known/**/*
- name: backend
imageBase:
image: devfra.azurecr.io/de.fraport.build/haskell
tag: 8.10.4
dependsOn:
- Build_frontend
dependenciesCaches:
- key: stack.yaml | stack.yaml.lock
path: .stack/
buildPool: 'Prod Private Agent Pool DS3'
buildCores: 3
buildTimeout: 1440
buildArtifacts: |
bin/*
variables:
buildImageUpstream: devfra.azurecr.io/de.fraport.fradrive.build
setupImages: $[ or( eq(variables.forcePushLatest, true), eq(variables['Build.SourceBranch'], 'refs/heads/master'), startsWith(variables['Build.SourceBranch'], 'refs/heads/update'), startsWith(variables['Build.SourceBranch'], 'refs/tags/') ) ]
pool: 'Prod Private Agent Pool'
stages:
- stage: Setup
jobs:
- ${{ each service in parameters.services }}:
- template: .azure-pipelines/templates/jobs/setup_image.yaml
parameters:
imageName: ${{service.name}}
imageBase: ${{service.imageBase}}
- template: .azure-pipelines/templates/jobs/setup_dependencies.yaml
parameters:
serviceName: ${{service.name}}
dependenciesCaches: ${{service.dependenciesCaches}}
dependenciesBuildPool: ${{service.buildPool}}
dependenciesBuildCores: ${{service.buildCores}}
dependenciesBuildTimeout: ${{service.buildTimeout}}
- stage: Build
dependsOn: Setup
jobs:
- ${{ each service in parameters.services }}:
- job: Build_${{service.name}}
displayName: Compile ${{service.name}}
dependsOn: ${{service.dependsOn}}
pool: '${{service.buildPool}}'
timeoutInMinutes: ${{service.buildTimeout}}
container:
${{ if eq(variables.setupImages, true) }}:
image: $(buildImageUpstream)/${{service.name}}:$(Build.BuildNumber)
${{ else }}:
image: $(buildImageUpstream)/${{service.name}}:latest
endpoint: devfra
env:
PROJECT_DIR: $(Build.Repository.LocalPath)
IN_CONTAINER: true
IN_CI: true
steps:
- ${{ each dependencyCache in service.dependenciesCaches }}:
- template: .azure-pipelines/templates/steps/cache.yaml
parameters:
cacheIdent: '${{service.name}}-dependencies'
cacheKeys: '${{dependencyCache.key}}'
cachePath: '${{dependencyCache.path}}'
- ${{ each dependency in service.dependsOn }}:
- template: .azure-pipelines/templates/steps/artifact-download.yaml
parameters:
artifactName: '${{dependency}}'
- template: .azure-pipelines/templates/steps/make.yaml
parameters:
makeJob: compile
makeService: ${{service.name}}
makeVars: 'CPU_CORES=${{service.buildCores}} STACK_CORES=-j${{service.buildCores}}'
- task: CopyFiles@2
displayName: Prepare ${{service.name}} build artifacts for upload
inputs:
Contents: '${{service.buildArtifacts}}'
TargetFolder: '$(Build.ArtifactStagingDirectory)'
- task: PublishBuildArtifacts@1
displayName: Publish ${{service.name}} build artifacts
inputs:
PathtoPublish: '$(Build.ArtifactStagingDirectory)'
ArtifactName: 'Build_${{service.name}}'
publishLocation: 'Container'
# - stage: Test
# dependsOn: Build
# condition: eq(variables.skipTests, false)
# jobs:
# - ${{ each service in parameters.services }}:
# - job: Test_${{service.name}}
# displayName: Run ${{service.name}} tests
# pool: '${{service.buildPool}}'
# timeoutInMinutes: ${{service.buildTimeout}}
# container:
# # TODO: do not use latest on update branches
# image: $(buildImageUpstream)/${{service.name}}:latest
# endpoint: devfra
# env:
# PROJECT_DIR: $(Build.Repository.LocalPath)
# IN_CONTAINER: true
# IN_CI: true
# steps:
# - ${{ each dependencyCache in service.dependenciesCaches }}:
# - template: .azure-pipelines/templates/steps/cache.yaml
# parameters:
# cacheIdent: '${{service.name}}-dependencies'
# cacheKeys: '${{dependencyCache.key}}'
# cachePath: '${{dependencyCache.path}}'
# - ${{ each dependency in service.dependsOn }}:
# - template: .azure-pipelines/templates/steps/artifact-download.yaml
# parameters:
# artifactName: '${{dependency}}'
# - task: Docker@2
# displayName: Login to container registry
# inputs:
# command: login
# containerRegistry: devfra
# - task: Bash@3
# displayName: Start database container for testing
# inputs:
# targetType: inline
# script: |
# docker run -d devfra.azurecr.io/de.fraport.trusted/postgres:16.1-bookworm
# - template: .azure-pipelines/templates/steps/make.yaml
# parameters:
# makeJob: lint
# makeService: ${{service.name}}
# makeVars: 'CPU_CORES=${{service.buildCores}} STACK_CORES=-j${{service.buildCores}}'
# - template: .azure-pipelines/templates/steps/make.yaml
# parameters:
# makeJob: test
# makeService: ${{service.name}}
# makeVars: 'CPU_CORES=${{service.buildCores}} STACK_CORES=-j${{service.buildCores}}'
# - task: Docker@2
# displayName: Logout from container registry
# inputs:
# command: logout
# containerRegistry: devfra
# - job: TestReport_${{service.name}}
# displayName: Upload test reports for ${{service.name}}
# steps:
# - script: echo "Work in progress" # TODO
- stage: Release
dependsOn: Build # TODO Test
condition: or(eq(variables.forceRelease, true), startsWith(variables['Build.SourceBranch'], 'refs/tags/'))
jobs:
- template: .azure-pipelines/templates/jobs/release.yaml
parameters:
releaseTag: ${{split(variables['Build.SourceBranch'], '/')[2]}}
jobs:
# - job: HelloWorld
# container:
# image: 'devfra.azurecr.io/de.fraport.trusted/ubuntu:22.04'
# endpoint: devfra
# steps:
# - script: echo Hello, world!
# displayName: 'Run a one-line script'
# - script: |
# echo Add other tasks to build, test, and deploy your project.
# echo See https://aka.ms/yaml
# displayName: 'Run a multi-line script'
- job: DockerTaskTest
container:
image: devfra.azurecr.io/de.fraport.build/tools:1.1.0
endpoint: devfra
steps:
- task: Docker@2
name: dockerLoginDevFra
displayName: Docker Login to devfra
inputs:
command: login
containerRegistry: devFra
- task: Docker@2
name: dockerBuild
displayName: Backend image build test
inputs:
command: build
Dockerfile: docker/backend/Dockerfile
buildContext: .
tags: |
$(Build.BuildNumber)
backend
arguments: |
--build-arg HTTPS_PROXY=http://proxy.frankfurt-airport.de:8080
--build-arg HTTP_PROXY=http://proxy.frankfurt-airport.de:8080
--build-arg NO_PROXY='localhost,127.0.0.1,*.docker.internal,*.azmk8s.io,devfra.azurecr.io,devfra.westeurope.data.azurecr.io'
--build-arg PROJECT_DIR=/fradrive
--build-arg MOUNT_DIR=/mnt/fradrive
# - job: BuildKitTest
# container:
# image: 'devfra.azurecr.io/de.fraport.trusted/buildkit:0.12.1'
# endpoint: devfra
# steps:
# - script: buildctl build \
# --frontend=dockerfile.v0 \
# --local context=. \
# --local dockerfile=docker/backend/Dockerfile
# displayName: BuildKit test
# - job: CustomBuildahTest
# container:
# image: 'devfra.azurecr.io/de.fraport.trusted/ubuntu:22.04'
# endpoint: devfra
# steps:
# - script: |
# id
# docker build --help
# sudo apt-get -y update
# sudo apt-get -y install buildah
# buildah bud -t fradrive-backend-test --volume .:/mnt/fradrive --file docker/backend/Dockerfile
# displayName: Build buildah image

View File

@ -2,4 +2,4 @@
//
// SPDX-License-Identifier: AGPL-3.0-or-later
module.exports = {extends: ['@commitlint/config-conventional']};
module.exports = {extends: ['@commitlint/config-conventional']}

View File

@ -0,0 +1,30 @@
# SPDX-FileCopyrightText: 2024 Steffen Jost <s.jost@fraport.de>
#
# SPDX-License-Identifier: AGPL-3.0-or-later
# Values formatted like "_env:ENV_VAR_NAME:default_value" can be overridden by the specified environment variable.
# See https://github.com/yesodweb/yesod/wiki/Configuration#overriding-configuration-values-with-environment-variables
# NB: If you need a numeric value (e.g. 123) to parse as a String, wrap it in single quotes (e.g. "_env:PGPASS:'123'")
# See https://github.com/yesodweb/yesod/wiki/Configuration#parsing-numeric-values-as-strings
#DEVELOPMENT ONLY, NOT TO BE USED IN PRODUCTION
avs-licence-synch:
times: [12]
level: 4
reason-filter: "(firm|block)"
max-changes: 999
mail-reroute-to:
name: FRADrive-QA-Umleitungen
email: FRADrive-TEST-Umleitungen@fraport.de
# Enqueue at specified hour, a few minutes later
job-lms-qualifications-enqueue-hour: 16
job-lms-qualifications-dequeue-hour: 4
job-mode:
tag: offload
job-workers: 1
job-flush-interval: 600

View File

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2022-2024 Sarah Vaupel <sarah.vaupel@uniworx.de>, Gregor Kleen <gregor.kleen@ifi.lmu.de>,Sarah Vaupel <sarah.vaupel@ifi.lmu.de>,Steffen Jost <jost@tcs.ifi.lmu.de>,Wolfgang Witt <Wolfgang.Witt@campus.lmu.de>
# SPDX-FileCopyrightText: 2022-2025 Sarah Vaupel <sarah.vaupel@uniworx.de>, Gregor Kleen <gregor.kleen@ifi.lmu.de>,Sarah Vaupel <sarah.vaupel@ifi.lmu.de>,Steffen Jost <jost@tcs.ifi.lmu.de>,Wolfgang Witt <Wolfgang.Witt@campus.lmu.de>,Steffen Jost <s.jost@fraport.de>
#
# SPDX-License-Identifier: AGPL-3.0-or-later
@ -83,6 +83,7 @@ health-check-matching-cluster-config-timeout: "_env:HEALTHCHECK_MATCHING_CLUSTER
synchronise-ldap-users-within: "_env:SYNCHRONISE_LDAP_WITHIN:1209600" # 14 Tage in Sekunden
synchronise-ldap-users-interval: "_env:SYNCHRONISE_LDAP_INTERVAL:3600" # jede Stunde
synchronise-ldap-users-expire: "_env:SYNCHRONISE_LDAP_EXPIRE:15897600" # halbes Jahr in Sekunden
synchronise-avs-users-within: "_env:SYNCHRONISE_AVS_WITHIN:5702400" # alle 66 Tage
synchronise-avs-users-interval: "_env:SYNCHRONISE_AVS_INTERVAL:21600" # alle 6 Stunden
@ -90,10 +91,6 @@ synchronise-avs-users-interval: "_env:SYNCHRONISE_AVS_INTERVAL:21600" # alle 6
study-features-recache-relevance-within: 172800
study-features-recache-relevance-interval: 293
# Enqueue at specified hour, a few minutes later
# job-lms-qualifications-enqueue-hour: 15
# job-lms-qualifications-dequeue-hour: 3
log-settings:
detailed: "_env:DETAILED_LOGGING:false"
all: "_env:LOG_ALL:false"
@ -149,18 +146,22 @@ ldap:
ldap-re-test-failover: 60
lms-direct:
upload-header: "_env:LMSUPLOADHEADER:true"
upload-delimiter: "_env:LMSUPLOADDELIMITER:"
download-header: "_env:LMSDOWNLOADHEADER:true"
download-delimiter: "_env:LMSDOWNLOADDELIMITER:,"
download-cr-lf: "_env:LMSDOWNLOADCRLF:true"
deletion-days: "_env:LMSDELETIONDAYS:7"
upload-header: "_env:LMSUPLOADHEADER:true"
upload-delimiter: "_env:LMSUPLOADDELIMITER:"
download-header: "_env:LMSDOWNLOADHEADER:true"
download-delimiter: "_env:LMSDOWNLOADDELIMITER:,"
download-cr-lf: "_env:LMSDOWNLOADCRLF:true"
orphan-deletion-days: "_env:LMSORPHANDELETIONDAYS:33"
orphan-deletion-batch: "_env:LMSORPHANDELETIONBATCH:12"
orphan-deletion-repeat-hours: "_env:LMSORPHANDELETIONREPEATHOURS:24"
avs:
host: "_env:AVSHOST:skytest.fra.fraport.de"
port: "_env:AVSPORT:443"
user: "_env:AVSUSER:fradrive"
pass: "_env:AVSPASS:"
host: "_env:AVSHOST:skytest.fra.fraport.de"
port: "_env:AVSPORT:443"
user: "_env:AVSUSER:fradrive"
pass: "_env:AVSPASS:\"0000\""
timeout: "_env:AVSTIMEOUT:42"
cache-expiry: "_env:AVSCACHEEXPIRY:420"
lpr:
host: "_env:LPRHOST:fravm017173.fra.fraport.de"
@ -207,9 +208,6 @@ memcached:
timeout: "_env:MEMCACHED_TIMEOUT:20"
expiration: "_env:MEMCACHED_EXPIRATION:300"
memcache-auth: true
memcached-local:
maximum-ghost: 512
maximum-weight: 104857600 # 100MiB
upload-cache:
host: "_env:UPLOAD_S3_HOST:localhost" # should be optional, but all file transfers will be empty without an S3 cache
@ -278,8 +276,8 @@ user-defaults:
max-favourites: 0
max-favourite-terms: 2
theme: Default
date-time-format: "%d %b %y %R"
date-format: "%d %b %Y"
date-time-format: "%d.%m.%Y %R"
date-format: "%d.%m.%y"
time-format: "%R"
download-files: false
warning-days: 1209600
@ -321,17 +319,6 @@ fallback-personalised-sheet-files-keys-expire: 2419200
download-token-expire: 604801
file-source-arc:
maximum-ghost: 512
maximum-weight: 1073741824 # 1GiB
file-source-prewarm:
maximum-weight: 1073741824 # 1GiB
start: 1800 # 30m
end: 600 # 10m
inhibit: 3600 # 60m
steps: 20
max-speedup: 3
bot-mitigations:
- only-logged-in-table-sorting
- unauthorized-form-honeypots

View File

@ -1,38 +1,41 @@
ARG FROM_IMG=docker.io/library/haskell
ARG FROM_TAG=8.10.4
FROM docker.io/fpco/stack-build:lts-18.0
FROM ${FROM_IMG}:${FROM_TAG}
# add public key for nvidia cuda repositories
RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A4B469963BF863CC
ENV LANG=de_DE.UTF-8
ENV LANG=en_US.UTF-8
# compile-time dependencies
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
apt-get -y update && apt-get install -y libpq-dev libsodium-dev
# RUN apt-get -y update && apt-get -y install llvm
# RUN apt-get -y update && apt-get -y install g++ libghc-zlib-dev libpq-dev libsodium-dev pkg-config
# RUN apt-get -y update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends tzdata
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
apt-get -y update && apt-get install -y --no-install-recommends locales locales-all
# RUN apt-get -y update && apt-get -y install locales locales-all
# run-time dependencies for uniworx binary
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
apt-get -y update && apt-get -y install fonts-roboto
# RUN apt-get -y update && apt-get -y install fonts-roboto
# RUN apt-get -y update && apt-get -y install pdftk
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
apt-get -y update && apt-get -y install texlive-latex-recommended texlive-luatex texlive-plain-generic texlive-lang-german texlive-lang-english
# RUN apt-get -y update && apt-get -y install texlive-base luatex
# locally these two should be identical, so that compilation results are written out into the file dir.
# in CI-pipelines these two should be different, so that the container caches the compilation results.
ARG MOUNT_DIR=/mnt/fradrive
ARG PROJECT_DIR=/fradrive
ENV PROJECT_DIR=${PROJECT_DIR}
RUN mkdir -p "${PROJECT_DIR}"; chmod -R 7777 "${PROJECT_DIR}"
WORKDIR ${PROJECT_DIR}
ENV HOME=${PROJECT_DIR}
RUN mkdir -p "${PROJECT_DIR}"
RUN if [ "${PROJECT_DIR}" != "${MOUNT_DIR}" ] ; then cp -r "${MOUNT_DIR}"/* "${PROJECT_DIR}" ; fi
RUN mkdir -p "${PROJECT_DIR}/.stack"
ENV STACK_ROOT="${PROJECT_DIR}/.stack"
RUN if [ ! -z "${IN_CI}" ]; then \
stack install yesod-bin; \
stack install hpack; \
fi
WORKDIR ${PROJECT_DIR}
ENV HOME=${PROJECT_DIR}
RUN make -- --dependencies-backend STACK_ROOT=${STACK_ROOT} IN_CONTAINER=true JOB=${JOB}
RUN stack install yesod-bin
RUN stack install hpack
ENV FRADRIVE_MAKE_TARGET=--start-backend
ENTRYPOINT make -- ${FRADRIVE_MAKE_TARGET} STACK_ROOT="${STACK_ROOT}" IN_CONTAINER=true CONTAINER_FILE="${CONTAINER_FILE}" JOB="${JOB}" SRC="${SRC}"
EXPOSE 3000/tcp
EXPOSE 3443/tcp

19
docker/fradrive/Dockerfile Executable file → Normal file
View File

@ -1,13 +1,12 @@
ARG FROM_IMG=docker.io/library/debian
ARG FROM_TAG=12.5
FROM debian:12.5
FROM ${FROM_IMG}:${FROM_TAG}
RUN apt-get -y update
# Setup locales
# RUN apt-get update && apt-get -y install locales locales-all
# RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && \
# locale-gen
# ENV LANG=en_US.UTF-8 LANGUAGE=en_US:en LC_ALL=en_US.UTF-8
# setup locales
RUN apt-get -y install locales locales-all
RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && \
locale-gen
ENV LANG=en_US.UTF-8 LANGUAGE=en_US:en LC_ALL=en_US.UTF-8
# FraDrive runtime dependencies
ENV DEBIAN_FRONTEND=noninteractive
@ -31,7 +30,7 @@ RUN useradd -r -g uniworx -d /var/lib/uniworx -M uniworx --uid 999
RUN mkdir -p /var/lib/uniworx && chown -R uniworx:uniworx /var/lib/uniworx
RUN mkdir -p /var/log/uniworx && chown -R uniworx:uniworx /var/log/uniworx
# Install FraDrive binaries
# TODO: is this still needed?
# RUN install -d -g uniworx -o uniworx -m 0750 /var/lib/uniworx
# RUN install -d -g uniworx -o uniworx -m 0755 /var/log/uniworx
COPY ./bin/uniworx /usr/bin/uniworx
@ -42,6 +41,6 @@ COPY ./docker/fradrive/fradrive-entrypoint.sh /entrypoint.sh
RUN chmod 777 /entrypoint.sh
USER uniworx
ENTRYPOINT /entrypoint.sh
ENTRYPOINT fradrive-entrypoint.sh
EXPOSE 8080/tcp
VOLUME /var/lib/uniworx /var/log

View File

@ -1,29 +1,32 @@
ARG FROM_IMG=docker.io/library/node
ARG FROM_TAG=20
FROM debian:12.5
FROM ${FROM_IMG}:${FROM_TAG}
# Basic dependencies
RUN apt-get -y update && apt-get -y install curl npm
ENV LANG=de_DE.UTF-8
ENV LANGUAGE=de_DE.UTF-8
# build and watch dependencies
# Build and watch dependencies
RUN apt-get -y update && apt-get -y install exiftool
RUN apt-get -y update && apt-get -y install imagemagick
# test dependencies
# RUN apt-get -y update && apt-get -y install chromium
# ENV CHROME_BIN=chromium
# Test dependencies
RUN apt-get -y update && apt-get -y install chromium
ENV CHROME_BIN=chromium
# configure npm to use given proxy if specified
RUN if [ ! -z "${HTTP_PROXY}" ]; then npm config set proxy ${HTTP_PROXY}; fi
RUN if [ ! -z "${FRAPORT_NOPROXY}" ]; then npm config set noproxy "${FRAPORT_NOPROXY}"; fi
ENV NODE_EXTRA_CA_CERTS="/etc/ssl/certs/ca-certificates.crt"
# TODO: use dotenv for npm version?
RUN npm install -g n
RUN n 20.17.0
ENV PROJECT_DIR=/fradrive
# locally these two should be identical, so that compilation results are written out into the file dir.
# in CI-pipelines these two should be different, so that the container caches the compilation results.
ARG MOUNT_DIR=/mnt/fradrive
ARG PROJECT_DIR=/fradrive
RUN mkdir -p ${PROJECT_DIR}
RUN if [ "${PROJECT_DIR}" != "${MOUNT_DIR}" ] ; then cp -r ${MOUNT_DIR}/* ${PROJECT_DIR} ; fi
WORKDIR ${PROJECT_DIR}
ENV HOME=${PROJECT_DIR}
RUN if [ ! -z "${NPM_CUSTOM_REGISTRY}" ]; then \
printf 'registry=${NPM_CUSTOM_REGISTRY}' > .npmrc \
; fi
#RUN make node_modules IN_CONTAINER=true
#RUN make well-known IN_CONTAINER=true
RUN make -- static
ENV FRADRIVE_MAKE_TARGET=start-frontend
ENTRYPOINT make -- ${FRADRIVE_MAKE_TARGET} IN_CONTAINER=true CHROME_BIN=${CHROME_BIN}

33
docker/podman/Dockerfile Normal file
View File

@ -0,0 +1,33 @@
# Debian-based podman daemon image for building docker images
# inside docker containers (e.g. gitlab runners).
#
# Yoinked with love from:
# https://www.redhat.com/sysadmin/podman-inside-container
FROM debian:12.5
RUN apt-get -y update
RUN apt-get -y install make podman podman-compose fuse-overlayfs
RUN useradd podman; \
echo podman:10000:5000 > /etc/subuid; \
echo podman:10000:5000 > /etc/subgid;
VOLUME /var/lib/containers
VOLUME /home/podman/.local/share/containers
ADD https://raw.githubusercontent.com/containers/image_build/main/podman/containers.conf /etc/containers/containers.conf
ADD https://raw.githubusercontent.com/containers/image_build/main/podman/podman-containers.conf /home/podman/.config/containers/containers.conf
RUN chown podman:podman -R /home/podman
# chmod containers.conf and adjust storage.conf to enable Fuse storage.
# RUN chmod 644 /etc/containers/containers.conf; sed -i -e 's|^#mount_program|mount_program|g' -e '/additionalimage.*/a "/var/lib/shared",' -e 's|^mountopt[[:space:]]*=.*$|mountopt = "nodev,fsync=0"|g' /etc/containers/containers.conf
# RUN echo -e '[storage]\ndriver="zfs"\nmount_program="zfs"\nadditionalimage=/var/lib/shared\nmountopt="nodev,fsync=0"' >> /etc/containers/containers.conf
RUN chmod 644 /etc/containers/containers.conf
RUN echo '[storage]\ndriver="overlay"\n[storage.options.overlay]\nforce_mask="private"\nmount_program="/usr/bin/fuse-overlayfs"\nmountopt="nodev"' >> /etc/containers/containers.conf
RUN mkdir -p /root/.config/containers/ && echo '[storage]\ndriver="overlay"\n[storage.options.overlay]\nforce_mask="private"\nmount_program="/usr/bin/fuse-overlayfs"\nmountopt="nodev"' > /root/.config/containers/storage.conf
RUN mkdir -p /var/lib/shared/overlay-images /var/lib/shared/overlay-layers /var/lib/shared/vfs-images /var/lib/shared/vfs-layers; touch /var/lib/shared/overlay-images/images.lock; touch /var/lib/shared/overlay-layers/layers.lock; touch /var/lib/shared/vfs-images/images.lock; touch /var/lib/shared/vfs-layers/layers.lock
ENV _CONTAINERS_USERNS_CONFIGURED=""

View File

@ -7,8 +7,8 @@ import svgPlugin from 'esbuild-plugin-svg-bundle';
import { copy } from 'esbuild-plugin-copy';
// import manifestPlugin from 'esbuild-plugin-manifest';
import manifestPlugin from 'esbuild-plugin-assets-manifest';
// import copyWithHashPlugin from '@enonic/esbuild-plugin-copy-with-hash';
// import inlineImportPlugin from 'esbuild-plugin-inline-import';
import copyWithHashPlugin from '@enonic/esbuild-plugin-copy-with-hash';
import inlineImportPlugin from 'esbuild-plugin-inline-import';
import { nodeModulesPolyfillPlugin } from 'esbuild-plugins-node-modules-polyfill';
const staticDir = './static';

View File

@ -5,7 +5,7 @@ import babelParser from "@babel/eslint-parser";
export default [
js.configs.recommended,
{
files: ["frontend/src/**/*.js"],
files: ["**/*.js"],
plugins: {},
languageOptions: {
ecmaVersion: 2018,

View File

@ -1,11 +1,10 @@
// SPDX-FileCopyrightText: 2024-2025 David Mosbach <david.mosbach@uniworx.de>, Sarah Vaupel <sarah.vaupel@uniworx.de>
// SPDX-FileCopyrightText: 2024 David Mosbach <david.mosbach@uniworx.de>, Sarah Vaupel <sarah.vaupel@uniworx.de>
//
// SPDX-License-Identifier: AGPL-3.0-or-later
// SPDX-License-Identifier: LicenseRef-Fraport-Corporate-Design
@import 'env';
$ico-width: 30px;
$ico-width: 15px;
$icons: new,
ok,
@ -35,6 +34,7 @@ $icons: new,
file-upload,
file-zip,
file-csv,
file-missing,
sft-question,
sft-hint,
sft-solution,
@ -95,15 +95,21 @@ $icons: new,
trash,
reset-tries,
company,
company-warning,
edit,
user-edit,
placeholder,
glasses,
user-badge,
user-unknown,
missing,
pin-protect,
loading;
@each $name in $icons {
.ico-#{$name} {
background-image: url('#{$path}/assets/icons/fradrive/#{$name}.svg');
background-image: url('/mnt/fradrive/assets/icons/fradrive/#{$name}.svg');
background-size: contain;
background-repeat: no-repeat;
background-position: center;
@ -133,6 +139,7 @@ $icons: new,
.large-ico {
font-size: 2em;
min-width: 1em;
}
.ico-spin {

View File

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2022-2025 Sarah Vaupel <sarah.vaupel@uniworx.de>, Gregor Kleen <gregor.kleen@ifi.lmu.de>,Johannes Eder <ederj@cip.ifi.lmu.de>,Sarah Vaupel <sarah.vaupel@ifi.lmu.de>,Sarah Vaupel <vaupel.sarah@campus.lmu.de>
// SPDX-FileCopyrightText: 2022-2024 Sarah Vaupel <sarah.vaupel@uniworx.de>, Gregor Kleen <gregor.kleen@ifi.lmu.de>,Johannes Eder <ederj@cip.ifi.lmu.de>,Sarah Vaupel <sarah.vaupel@ifi.lmu.de>,Sarah Vaupel <vaupel.sarah@campus.lmu.de>
//
// SPDX-License-Identifier: AGPL-3.0-or-later
@ -499,14 +499,14 @@ function encrypt(plaintext, key) {
if (!key) throw new Error('Cannot encrypt plaintext without a valid key!');
// TODO use const if possible
// let plaintextB = Buffer.from(plaintext);
// let cipherB = Buffer.alloc(plaintextB.length + sodium.crypto_secretbox_MACBYTES);
// let nonceB = Buffer.alloc(sodium.crypto_secretbox_NONCEBYTES);
// let keyB = Buffer.from(key);
let plaintextB = Buffer.from(plaintext);
let cipherB = Buffer.alloc(plaintextB.length + sodium.crypto_secretbox_MACBYTES);
let nonceB = undefined; // Buffer.alloc(sodium.crypto_secretbox_NONCEBYTES);
let keyB = Buffer.from(key);
// sodium.crypto_secretbox_easy(cipherB, plaintextB, nonceB, keyB);
const result = null; // cipherB;
const result = cipherB;
console.log('encrypt result', result);
return result;
}
@ -519,10 +519,10 @@ function decrypt(ciphertext, key) {
if (!key) throw new Error('Cannot decrypt ciphertext without a valid key!');
// TODO use const if possible
// let cipherB = Buffer.from(ciphertext);
let plaintextB = null; // Buffer.alloc(cipherB.length - sodium.crypto_secretbox_MACBYTES);
// let nonceB = undefined; Buffer.alloc(sodium.crypto_secretbox_NONCEBYTES);
// let keyB = Buffer.from(key);
let cipherB = Buffer.from(ciphertext);
let plaintextB = undefined; Buffer.alloc(cipherB.length - sodium.crypto_secretbox_MACBYTES);
let nonceB = undefined; Buffer.alloc(sodium.crypto_secretbox_NONCEBYTES);
let keyB = Buffer.from(key);
// sodium.crypto_secretbox_open_easy(plaintextB, cipherB, nonceB, keyB);

View File

@ -163,7 +163,6 @@ input[type*='time'],
// TEXTAREAS
textarea
width: 100%
height: 170px
max-width: 600px
line-height: 1.5
color: #363636
@ -176,6 +175,8 @@ textarea
border-radius: 2px
box-shadow: inset 0 1px 2px 1px rgba(50, 50, 50, 0.05)
vertical-align: top
&:not(.uwx-short)
height: 172px
// SHARED STATE RELATED STYLES
@ -211,10 +212,11 @@ option
border-radius: 2px
outline: 0
color: #363636
min-width: 250px
width: auto
background-color: #f3f3f3
box-shadow: inset 0 1px 2px 1px rgba(50, 50, 50, 0.05)
&:not(.uwx-narrow)
min-width: 250px
@media (max-width: 425px)
select, option

View File

@ -2,7 +2,7 @@
//
// SPDX-License-Identifier: AGPL-3.0-or-later
/* eslint-disable */
module.exports = function(config) {
config.set({
//root path location to resolve paths defined in files and exclude

View File

@ -96,7 +96,7 @@ sampleIntegral = sampleN scaleIntegral
instance PathPiece DiffTime where
toPathPiece = (toPathPiece :: Pico -> Text) . MkFixed . diffTimeToPicoseconds
fromPathPiece t = fromPathPiece t <&> \(MkFixed ps :: Pico) -> picosecondsToDiffTime ps
data LoadSimulation
= LoadSheetDownload
@ -214,13 +214,13 @@ runSimulation sim = do
delays <- replicateM (fromIntegral p) $ do
d <- view $ _2 . _simDelay
sampleNDiffTime d
forConcurrently_ ([1..p] `zip` sort delays) $ \(n, d') -> do
begin <- liftIO getCurrentTime
dur <- view $ _2 . _simDuration
tDuration <- sampleNDiffTime dur
let MkFixed us = realToFrac d' :: Micro
threadDelay $ fromInteger us
start <- liftIO getCurrentTime
@ -268,7 +268,7 @@ runSimulation' LoadSheetSubmission = do
-- Just formData <- return . getFormData FIDsubmission $ resp ^. responseBody
-- Just addButtonData <- return . flip (runFormScraper FIDsubmission) (resp ^. responseBody) $ do
-- let btnSel = "button" Scalpel.@: [Scalpel.hasClass "btn-mass-input-add"]
-- name <- Scalpel.attr "name" btnSel
-- value <- Scalpel.attr "value" btnSel
-- guard $ value == "add__0__0"
@ -305,7 +305,7 @@ runSimulation' LoadSheetSubmission = do
procEnd <- join $ asks runtime
print ("proc", procEnd - procStart)
resp3 <- liftIO . httpRetry $ Session.post session (uriToString id formURI mempty) subData
void . evaluate $! resp3
where
@ -328,11 +328,11 @@ runSimulation' LoadSheetSubmission = do
-> m ()
logRetry shouldRetry err status = liftIO . putStrLn . pack $ Retry.defaultLogMsg shouldRetry err status
-- runSimulation' other = terror $ "Not implemented: " <> tshow other
runFormScraper :: FormIdentifier -> Scalpel.Scraper Lazy.ByteString a -> Lazy.ByteString -> Maybe a
runFormScraper fid innerS = fmap join . flip Scalpel.scrapeStringLike $
runFormScraper fid innerS = fmap join . flip Scalpel.scrapeStringLike $
fmap listToMaybe . Scalpel.chroots "form" $ do
fid' <- Scalpel.attr "value" $ "input" Scalpel.@: ["name" Scalpel.@= "form-identifier"]
guard $ fid' == encodeUtf8 (fromStrict $ toPathPiece fid)
@ -341,11 +341,11 @@ runFormScraper fid innerS = fmap join . flip Scalpel.scrapeStringLike $
getFormData :: FormIdentifier -> Lazy.ByteString -> Maybe [FormParam]
getFormData = flip runFormScraper $
Scalpel.chroots ("input") $ do
Scalpel.chroots "input" $ do
name <- Scalpel.attr "name" Scalpel.anySelector
value <- Scalpel.attr "value" Scalpel.anySelector <|> pure ""
return $ toStrict name := value
newLoadSession :: ReaderT SimulationContext IO Session
newLoadSession = do
@ -354,7 +354,7 @@ newLoadSession = do
let withToken = case loadToken of
Nothing -> id
Just (Jwt bs) -> (:) (hAuthorization, "Bearer " <> bs) . filter ((/= hAuthorization) . fst)
liftIO . Session.newSessionControl (Just mempty) $ tlsManagerSettings
{ managerModifyRequest = \req -> return $ req { requestHeaders = withToken $ requestHeaders req }

View File

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2022 Gregor Kleen <gregor.kleen@ifi.lmu.de>,Winnie Ros <winnie.ros@campus.lmu.de>
# SPDX-FileCopyrightText: 2022-25 Gregor Kleen <gregor.kleen@ifi.lmu.de>,Winnie Ros <winnie.ros@campus.lmu.de>,Steffen Jost <s.jost@fraport.de>
#
# SPDX-License-Identifier: AGPL-3.0-or-later
@ -67,6 +67,7 @@ BearerTokenExpiresTip: Wird der Ablaufzeitpunkt überschrieben und kein Ablaufze
BearerTokenOverrideStart: Startzeitpunkt
BearerTokenOverrideStartTip: Wird kein Startzeitpunkt angegeben, wird bei Verwendung des Tokens nur der Ablaufzeitpunkt überprüft.
HeadingAdminTokens: Tokens ausstellen
UserUnknown: Unbekannter Benutzer:in
#templates adminFeautures
StudyFeaturesDegrees: Abschlüsse
@ -101,18 +102,20 @@ ProblemsHeadingDrivers: Fahrberechtigungen
ProblemsHeadingNotifications: Benachrichtigungen
ProblemsHeadingMisc: Allgemein
ProblemsAvsProblem: Synchronisation mit AVS/MoBaKo komplett fehlgeschlagen
ProblemsDriverSynch n@Int: #{tshow n} Diskrepanzen zwischen AVS und FRADrive
ProblemsDriverSynch n@Int: #{n} #{pluralDE n "Diskrepanz" "Diskrepanzen"} zwischen AVS und FRADrive
ProblemsDriverSynch0: Alle Sperrungen von Vorfeld-Fahrberechtigungen 'F' sind im AVS eingetragen
ProblemsDriverSynch1down: Alle Sperrungen von Rollfeld-Fahrberechtigungen 'R' sind im AVS eingetragen
ProblemsDriverSynch1up: Alle gültigen Vorfeld-Fahrberechtigungen 'F' sind im AVS eingetragen
ProblemsDriverSynch2: Alle gültigen Rollfeld-Fahrberechtigungen 'R' sind im AVS eingetragen
ProblemsRDriversHaveFs: Alle Inhaber einer Rollfeld-Fahrberechtigung besitzen auch eine gültige Vorfeld-Fahrberechtigung
ProblemsDriversHaveAvsIds: Alle Inhaber einer Fahrberechtigung konnten einer AVS Identifikationsnummer zugeordnet werden
ProblemsUsersAreReachable: Für alle Benutzer ist eine E-Mail oder postalische Adresse bekannt
ProblemsNoStalePrintJobs n@Integer: Alle Briefversandaufträge der vergangenen #{show n} Tage wurden von der Druckerei bestätigt
ProblemsUsersAreReachable: Für alle Benutzer ist eine E-Mail oder postalische Adresse bekannt
ProblemsNoStalePrintJobs n@Integer: Alle Briefversandaufträge #{pluralDE n "des vergangenen Tages" ("der vergangenen "<> tshow n <> " Tage")} wurden von der Druckerei bestätigt
ProblemsNoBadAPCIds: Alle kürzlich empfangenen Druckauftragsbestätigungen waren gültig
ProblemsNoInsaneCompanySupervisions: Sind alle Firmen-bezogenen Ansprechpartnerbeziehungen zwischen passenden Firmenangehörigen?
ProblemsUnreachableHeading: Unerreichbare Benutzer
ProblemsUnreachableBody: Benutzer ohne E-Mail oder Postadresse, welche z.B. bei ablaufenden Berechtigungen nicht benachrichtigt werden können:
ProblemsUnreachableButtons: Synchronisation für Unerreichbare starten
ProblemsRWithoutFHeading: Fahrer mit R ohne F
ProblemsRWithoutFBody: Diese Fahrer sind wegen einer ungültigen Vorfeld-Fahrberechtigung komplett gesperrt, obwohl eine gültige Rollfeld-Fahrberechtigung besteht:
ProblemsNoAvsIdHeading: Fahrer ohne AVS-Id
@ -120,6 +123,25 @@ ProblemsNoAvsIdBody: Fahrer mit gültiger Fahrberechtigung in FRADrive, welche t
ProblemsAvsSynchHeading: Synchronisation AVS Fahrberechtigungen
ProblemsAvsErrorHeading: Fehlermeldungen
ProblemsInterfaceSince: Berücksichtigt werden nur Erfolge und Fehler seit
ProblemAvsUsrHadR: Momentan gültiges R im AVS
ProblemLastCheckTime t@Text: Letzte Prüfung vor #{t}
AdminProblemSolved: Erledigt
AdminProblemSolver: Bearbeitet von
AdminProblemCreated: Erkannt
AdminProblemInfo: Problembeschreibung
AdminProblemsSolved n@Int: #{pluralDEeN n "Admin Problem"} als erledigt markiert
AdminProblemsReopened n@Int: #{pluralDEeN n "Admin Problem"} erneut eröffnet
AdminProblemNewCompany: Neue Firma über AVS automatisch erstellt; prüfen und ggf. Standardansprechpartner eintragen
AdminProblemSupervisorNewCompany b@Bool: Standardansprechpartner #{boolText mempty "mit Standardumleitung" b} wechselte zu neuer Firma
AdminProblemSupervisorLeftCompany b@Bool: Einziger Standardansprechpartner #{boolText mempty "mit Standardumleitung" b} dieses Fahrers wechselte zu neuer Firma
AdminProblemCompanySuperiorChange: Neuer firmenweiter Vorgesetzter.
AdminProblemCompanySuperiorNotFound t@Text: Neuer unbekannter firmenweiter Vorgesetzter mit E-Mail #{t}, keine Ansprechpartnerbeziehungen eingerichtet.
AdminProblemCompanySuperiorPrevious: Ehemaliger Vorgesetzter:
AdminProblemNewlyUnsupervised: Fahrer hat keinen Firmenansprechpartner mehr nach AVS Firmenwechsel zu Firma
AdminProblemUser: Betroffener
ProblemTableMarkSolved: Als erledigt markieren
ProblemTableMarkUnsolved: Erledigt Markierung löschen
InterfacesOk: Schnittstellen sind ok.
InterfacesFail n@Int: #{pluralDEeN n "Schnittstellenproblem"}!
@ -130,4 +152,13 @@ InterfaceSubtype: Betreffend
InterfaceWrite: Schreibend
InterfaceSuccess: Rückmeldung
InterfaceInfo: Nachricht
InterfaceFreshness: Prüfungszeitraum (h)
InterfaceFreshness: Maximale Zugriffsfrist
InterfaceFreshnessTooltip: Zeitspanne innerhalb der ein erneuter erfolgreicher Schnittstellenzugriff erfolgen muss, ohne Warnungen auszulösen
ConfigInterfacesHeading: Konfiguration Zugriffsfristen
IWTActAdd: Hinzufügen/Ändern
IWTActDelete: Entfernen
InterfaceWarningAdded: Schnittstellenwarnungszeit hinzugefügt oder geändert
InterfaceWarningDeleted n@Int: #{pluralDEeN n "Schnittstellenwarnungszeit"} gelöscht
InterfaceWarningDisabledEntirely: Alle Fehler ignorieren
InterfaceWarningDisabledInterval: Keine Zugriffsfrist

View File

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2022 Sarah Vaupel <sarah.vaupel@ifi.lmu.de>,Winnie Ros <winnie.ros@campus.lmu.de>
# SPDX-FileCopyrightText: 2022-25 Sarah Vaupel <sarah.vaupel@ifi.lmu.de>,Winnie Ros <winnie.ros@campus.lmu.de>,Steffen Jost <s.jost@fraport.de>
#
# SPDX-License-Identifier: AGPL-3.0-or-later
@ -18,10 +18,10 @@ NoNameCandidatesInferred: No new name-mappings inferred
AllNameIncidencesDeleted: Successfully deleted all name observations
AllParentIncidencesDeleted: Successfully deleted all parent-relation observations
AllStandaloneIncidencesDeleted: Successfully deleted all standalone observations
IncidencesDeleted n: Successfully deleted #{show n} #{pluralEN n "observation" "observations"}
RedundantParentCandidatesRemoved n: Successfully removed #{n} rendundant #{pluralEN n "parent-candidate" "parent-candidates"}
RedundantStandaloneCandidatesRemoved n: Successfully removed #{n} rendundant #{pluralEN n "standalone-candidate" "standalone-candidates"}
ParentCandidatesInferred n: Successfully inferred #{n} field #{pluralEN n "parent-relation" "parent-reliations"}
IncidencesDeleted n: Successfully deleted #{pluralENsN n "observation"}
RedundantParentCandidatesRemoved n: Successfully removed #{n} rendundant #{pluralENs n "parent-candidate"}
RedundantStandaloneCandidatesRemoved n: Successfully removed #{n} rendundant #{pluralENs n "standalone-candidate"}
ParentCandidatesInferred n: Successfully inferred #{n} field #{pluralENs n "parent-relation"}
NoParentCandidatesInferred: No new parent-relations inferred
StudyDegreeChangeSuccess: Successfully updated degrees
StudyTermsShort: Field shorthand
@ -67,6 +67,7 @@ BearerTokenExpiresTip: If no expiration time is given, the token will not expire
BearerTokenOverrideStart: Start time
BearerTokenOverrideStartTip: If no start time is given, only the expiration time will be checked when the token is used.
HeadingAdminTokens: Issue tokens
UserUnknown: User unknown
#templates adminfeatures
StudyFeaturesDegrees: Degrees
@ -101,7 +102,7 @@ ProblemsHeadingDrivers: Driving Licences
ProblemsHeadingNotifications: User communication
ProblemsHeadingMisc: Miscellaneous
ProblemsAvsProblem: Synchronisation with AVS/MoBaKo failed entirely
ProblemsDriverSynch n: #{tshow n} mismatches between AVS and FRADrive
ProblemsDriverSynch n: #{tshow n} #{pluralEN n "mismatch" "mismatches"} between AVS and FRADrive
ProblemsDriverSynch0: All revocations of apron driving licences 'F' were successfully registered with AVS
ProblemsDriverSynch1down: All revocations of maneuvering area driving licences 'R' were successfully registered with AVS
ProblemsDriverSynch1up: All valid apron driving licences 'F' were successfully registered with AVS
@ -109,17 +110,38 @@ ProblemsDriverSynch2: All valid maneuvering area driving licences 'R' were succe
ProblemsRDriversHaveFs: All driving licence 'R' holders also have a valid 'F' licence
ProblemsDriversHaveAvsIds: All driving licence holder could be matched with their AVS id
ProblemsUsersAreReachable: Either Email or postal address is known for all users
ProblemsNoStalePrintJobs n: All requests for letter mailing within the last #{show n} days were acknowledged as printed by the airport printing center
ProblemsNoStalePrintJobs n: All requests for letter mailing within the last #{pluralENsN n "day"} were acknowledged as printed by the airport printing center
ProblemsNoBadAPCIds: All recently received print job ids from Airport Print Center were legit
ProblemsNoInsaneCompanySupervisions: All company related supervisions are between company-associated users
ProblemsUnreachableHeading: Unreachable Users
ProblemsUnreachableBody: Users without Email nor postal address, who thus cannot be notified about expiring qualifications:
ProblemsUnreachableButtons: Start synchronisation for unreachable users only
ProblemsRWithoutFHeading: Drivers having 'R' but not 'F'
ProblemsRWithoutFBody: Drivers without apron driving licence are prohibited from driving, even if they own a valid maneuvering driving licence:
ProblemsNoAvsIdHeading: Drivers without AVS id
ProblemsNoAvsIdBody: Drivers having a valid apron driving licence within FRADrive only, but who may not drive since a missing AVS id prevents communication of the driving licence to AVS:
ProblemsAvsSynchHeading: Synchronisation AVS Driving Licences
ProblemsAvsErrorHeading: Error Log
ProblemsInterfaceSince: Only considering successes and errors since
ProblemsInterfaceSince: Only considering successes and errors since
ProblemAvsUsrHadR: Currenlt R valid in AVS
ProblemLastCheckTime t: Last checked #{t} ago
AdminProblemSolved: Done
AdminProblemSolver: Solved by
AdminProblemCreated: Recognized
AdminProblemInfo: Problem
AdminProblemsSolved n: #{pluralENsN n "admin problem"} marked as solved
AdminProblemsReopened n: #{pluralENsN n "admin problem"} reopened
AdminProblemNewCompany: New company from AVS; verify and add default supervisors
AdminProblemSupervisorNewCompany b: Default company supervisor #{boolText mempty "with reroute" b} changed to new company
AdminProblemSupervisorLeftCompany b: Only default company supervisor #{boolText mempty "with reroute" b} for this user changed to new company
AdminProblemCompanySuperiorChange: New company wide superior.
AdminProblemCompanySuperiorNotFound t: Unable to set supervision for new unknown company wide superior having Email #{t}.
AdminProblemCompanySuperiorPrevious: Previous superior:
AdminProblemNewlyUnsupervised: Driver has no longer a company default supervisor after AVS update at new company
AdminProblemUser: Affected
ProblemTableMarkSolved: Mark done
ProblemTableMarkUnsolved: Reopen as undone
InterfacesOk: Interfaces are ok.
InterfacesFail n: #{pluralENsN n "interface problem"}!
@ -130,4 +152,13 @@ InterfaceSubtype: Affecting
InterfaceWrite: Write
InterfaceSuccess: Returned
InterfaceInfo: Message
InterfaceFreshness: Check hours
InterfaceFreshness: Maximum usage period
InterfaceFreshnessTooltip: Time period within which the next successful interface access must occur to avoid a warning
ConfigInterfacesHeading: Configure interface usage warnings
IWTActAdd: Add/Edit
IWTActDelete: Delete
InterfaceWarningAdded: Interface warning time added/changed
InterfaceWarningDeleted n: #{pluralENsN n "interface warning time"} deleted
InterfaceWarningDisabledEntirely: Ignore all errors
InterfaceWarningDisabledInterval: No maximum usage period

View File

@ -26,30 +26,30 @@ UnauthorizedSiteAdmin: You are no system-wide administrator.
UnauthorizedSchoolAdmin: You are no administrator for this department.
UnauthorizedAdminEscalation: You aren't an administrator for all departments for which this user is an administrator.
UnauthorizedExamOffice: You are not part of an exam office.
UnauthorizedEvaluation: You are not charged with course type evaluation.
UnauthorizedEvaluation: You are not charged with course category evaluation.
UnauthorizedExamExamOffice: You are not part of the appropriate exam office for any of the participants of this exam.
UnauthorizedSchoolExamOffice: You are not part of an exam office for this school.
UnauthorizedSystemExamOffice: You are not charged with system wide exam administration.
UnauthorizedSystemPrinter: You are not charged with system wide letter printing.
UnauthorizedExternalExamExamOffice: You are not part of the appropriate exam office for any of the participants of this exam.
UnauthorizedSchoolLecturer: You are no course administrator for this department.
UnauthorizedLecturer: You are no administrator for this course type.
UnauthorizedCorrector: You are no sheet corrector for this course type.
UnauthorizedLecturer: You are no administrator for this course category.
UnauthorizedCorrector: You are no sheet corrector for this course category.
UnauthorizedSheetCorrector: You are no corrector for this sheet.
UnauthorizedExamCorrector: You are no corrector for this exam.
UnauthorizedCorrectorAny: You are no corrector for any course type.
UnauthorizedRegistered: You are no participant in this course type.
UnauthorizedCorrectorAny: You are no corrector for any course category.
UnauthorizedRegistered: You are no participant in this course category.
UnauthorizedRegisteredExam: You are not registered for this exam.
UnauthorizedRegisteredAnyExam: You are not registered for an exam.
UnauthorizedExamResult: You have no results in this exam.
UnauthorizedExamOccurrenceRegistration: Registration for exam is not done including occurrence/room.
UnauthorizedExternalExamResult: You have no results in this exam.
UnauthorizedParticipant: The specified user is no participant of this course type.
UnauthorizedParticipantSelf: You are no participant of this course type.
UnauthorizedCourseTime: This course type is not currently available.
UnauthorizedCourseRegistrationTime: This course type does not currently allow enrollment.
UnauthorizedParticipant: The specified user is no participant of this course category.
UnauthorizedParticipantSelf: You are no participant of this course category.
UnauthorizedCourseTime: This course category is not currently available.
UnauthorizedCourseRegistrationTime: This course category does not currently allow enrollment.
UnauthorizedSheetTime: This sheet is not currently available.
UnauthorizedMaterialTime: This course type material is not currently available.
UnauthorizedMaterialTime: This course category material is not currently available.
UnauthorizedTutorialTime: This course does not currently allow registration.
UnauthorizedCourseNewsTime: This news item is not currently available.
UnauthorizedExamTime: This exam is not currently available.
@ -61,7 +61,7 @@ UnauthorizedUserSubmission: Users may not directly submit for this exercise shee
UnauthorizedCorrectorSubmission: Correctors may not create submissions for this exercise sheet.
UnauthorizedCorrectionAnonymous: Correction is not anonymised.
DeprecatedRoute: This view is deprecated and will be removed.
UnfreeMaterials: Course type material are not publicly accessable.
UnfreeMaterials: Course category material are not publicly accessable.
UnauthorizedWrite: You do not have the write permission necessary to perform this action
UnauthorizedSystemMessageTime: This system-message is not currently available.
UnauthorizedSystemMessageAuth: This system-message is only available to logged in users.
@ -94,7 +94,7 @@ WorkflowRoleAlreadyInitiated: This workflow was already initiated
WorkflowRoleNoSuchWorkflowWorkflow: The given workflow could not be found
WorkflowRoleNoPayload: This workflow does not contain any data
CourseNoCapacity: Course type has reached maximum capacity
CourseNoCapacity: Course category has reached maximum capacity
TutorialNoCapacity: Course has reached maximum capacity
ExamOccurrenceNoCapacity: Occurrence/Room has reached maximum capacity
CourseNotEmpty: There are currently no participants enrolled for this course.

View File

@ -1,18 +1,22 @@
# SPDX-FileCopyrightText: 2022 Steffen Jost <jost@tcs.ifi.lmu.de>
# SPDX-FileCopyrightText: 2022-25 Steffen Jost <s.jost@fraport.de>
#
# SPDX-License-Identifier: AGPL-3.0-or-later
AvsPersonInfo: AVS Personendaten
AvsPersonId: AVS Personen Id
AvsPersonId: AVS Personen Id
AvsPersonNo: AVS Personennummer
AvsPersonNoNotId: AVS Personennummer dient zur menschlichen Kommunikation mit der Ausweisstelle und darf nicht verwechselt werden mit der maschinell verwendeten AVS Personen Id
AvsPersonNoMismatch: AVS Personennummer hat sich geändert und wurde in FRADrive noch nicht aktualisiert
AvsPersonNoDiffers: Es sind derzeit zwei verschiedene AVS Personennummern zugeordnet. Bitte einen Administrator kontaktieren.
AvsCardNo: Ausweiskartennummer
AvsFirstName: Vorname
AvsLastName: Nachname
AvsPrimaryCompany: Primäre Firma
AvsInternalPersonalNo: Personalnummer (nur Fraport AG)
AvsVersionNo: Versionsnummer
AvsQueryNeeded: Benötigt Verbindung zum AVS.
AvsQueryEmpty: Bitte mindestens ein Anfragefeld ausfüllen!
AvsQueryStatusInvalid t@Text: Nur numerische IDs eingeben, durch Komma getrennt! Erhalten: #{show t}
AvsLicence: Fahrberechtigung
AvsPersonNoNotId: AVS Personennummer dient zur menschlichen Kommunikation mit der Ausweisstelle und darf nicht verwechselt werden mit der maschinell verwendeten AVS Personen Id
AvsTitleLicenceSynch: Abgleich Fahrberechtigungen zwischen AVS und FRADrive
BtnAvsRevokeUnknown: Fahrberechtigungen im AVS sofort entziehen
BtnAvsImportUnknown: AVS Daten unbekannter Personen importieren
@ -27,13 +31,37 @@ RevokeFraDriveLicences alic@AvsLicence n@Int: _{alic} in FRADrive entzogen für
RevokeUnknownLicencesOk: AVS Fahrberechtigungen unbekannter Fahrer wurden gesperrt
RevokeUnknownLicencesFail: Nicht alle AVS Fahrberechtigungen unbekannter Fahrer konnten entzogen werden, siehe Log für Details
AvsCommunicationError: AVS Schnittstelle lieferte einen unerwarteten Fehler.
AvsCommunicationTimeout: AVS Schnittstelle antwortete nicht.
LicenceTableChangeAvs: Im AVS ändern
LicenceTableGrantFDrive: In FRADrive erteilen
LicenceTableRevokeFDrive: In FRADrive entziehen
TableAvsActiveCards: Gültige Ausweise
TableAvsCardValid: Aktuell gültig
TableAvsCardIssueDate: Ausgestellt am
TableAvsCardValidTo: Gültig bis
AvsCardAreas: Ausweiszusätze
AvsCardColor: Ausweisfarbe
AvsCardColorGreen: Grün
AvsCardColorBlue: Blau
AvsCardColorRed: Rot
AvsCardColorYellow: Gelb
LastAvsSynchronisation: Letzte AVS-Synchronisation
LastAvsSyncedBefore: Letzte AVS-Synchronisation vor
LastAvsSynchError: Letzte AVS-Fehlermeldung
AvsInterfaceUnavailable: AVS Schnittstelle nicht richtig konfiguriert oder antwortet nicht
AvsUserUnassociated user@UserDisplayName: AVS Id unbekannt für Nutzer #{user}
AvsUserUnknownByAvs api@AvsPersonId: AVS kennt Id #{tshow api} nicht (mehr)
AvsUserAmbiguous api@AvsPersonId: AVS Id #{tshow api} ist nicht eindeutig
AvsStatusSearchEmpty: AVS lieferte keine Ausweisinformationen
AvsPersonSearchEmpty: Suche im AVS lieferte kein Ergebnis
AvsPersonSearchAmbiguous: Suche im AVS lieferte mehrere uneindeutige Ergebnisse
AvsSetLicencesFailed reason@Text: Setzen der Fahrlizenz im AVS fehlgeschlagen. Grund: #{reason}
AvsIdMismatch api1@AvsPersonId api2@AvsPersonId: AVS Suche für Id #{tshow api1} lieferte stattdessen Id #{tshow api2}
AvsUserCreationFailed api@AvsPersonId: Für AVS Id #{tshow api} konnte kein neuer Benutzer angelegt werden, da es eine gemeinsame Id (z.B. Personalnummer) mit einem existierenden, aber verschiedenen Nutzer gibt.
AvsCardsEmpty: Suche im AVS lieferte keinerlei Ausweiskarten
AvsCurrentData: Alle angezeigte Daten wurden kürzlich direkt über die AVS Schnittstelle abgerufen.
AvsUpdateDayCheck: Zusätzlich wird im Hintergrund ein AVS Datenabgleich für alle in der Tagesansicht vorkommenden Personen angestoßen (einmal pro Tag).
AvsNoApronCard: Kein gültiger Ausweis mit Vorfeld-Zugang vorhanden
AvsNoCompanyCard mcn@(Maybe CompanyName): Für buchende Firma #{maybeEmpty mcn ciOriginal} liegt kein gültiger Ausweis vor

View File

@ -1,18 +1,23 @@
# SPDX-FileCopyrightText: 2022 Steffen Jost <jost@tcs.ifi.lmu.de>
# SPDX-FileCopyrightText: 2022-25 Steffen Jost <s.jost@fraport.de>
#
# SPDX-License-Identifier: AGPL-3.0-or-later
AvsPersonInfo: AVS Person Info
AvsPersonId: AVS Person Id
AvsPersonNo: AVS Person Number
AvsPersonInfo: AVS person info
AvsPersonId: AVS person id
AvsPersonNo: AVS person number
AvsPersonNoNotId: AVS person number is used in human communication only and must not be mistaken for the AVS personen id used in machine communications
AvsPersonNoMismatch: AVS person number has changed and was not yet updated in FRADrive
AvsPersonNoDiffers: There are currently two differing AVS person numbers associated with this user. Please contact an administrator to resolve this.
AvsCardNo: Card number
AvsFirstName: First name
AvsLastName: Last name
AvsPrimaryCompany: Primary company
AvsInternalPersonalNo: Personnel number (Fraport AG only)
AvsVersionNo: Version number
AvsQueryNeeded: AVS connection required.
AvsQueryEmpty: At least one query field must be filled!
AvsQueryStatusInvalid t: Numeric IDs only, comma seperated! #{show t}
AvsLicence: Driving Licence
AvsPersonNoNotId: AVS person number is used in human communication only and must not be mistaken for the AVS personen id used in machine communications
AvsTitleLicenceSynch: Synchronisation driving licences between AVS and FRADrive
BtnAvsRevokeUnknown: Revoke AVS driving licences for unknown persons immediately
BtnAvsImportUnknown: Import AVS data for unknown persons
@ -27,13 +32,37 @@ RevokeFraDriveLicences alic@AvsLicence n@Int: _{alic} revoked in FRADrive for #{
RevokeUnknownLicencesOk: AVS driving licences of unknown drivers revoked
RevokeUnknownLicencesFail: Not all AVS driving licences of unknown drivers could be revoked, see log for details
AvsCommunicationError: AVS interface returned an unexpected error.
AvsCommunicationTimeout: AVS interface returned no response within timeout limit.
LicenceTableChangeAvs: Change in AVS
LicenceTableGrantFDrive: Grant in FRADrive
LicenceTableRevokeFDrive: Revoke in FRADrive
TableAvsActiveCards: Valid Cards
TableAvsCardValid: Currently valid
TableAvsCardIssueDate: Issued
TableAvsCardValidTo: Valid to
AvsCardAreas: Card areas
AvsCardColor: Color
AvsCardColorGreen: Green
AvsCardColorBlue: Blue
AvsCardColorRed: Red
AvsCardColorYellow: Yellow
LastAvsSynchronisation: Last AVS synchronisation
LastAvsSynchError: Last AVS Error
LastAvsSyncedBefore: Last AVS synchronisation before
LastAvsSynchError: Last AVS Error
AvsInterfaceUnavailable: AVS interface was not configured correctly or does not respond
AvsUserUnassociated user: AVS id unknown for user #{user}
AvsUserUnknownByAvs api: AVS reports id #{tshow api} as unknown (or no longer known)
AvsUserAmbiguous api: Multiple matching users found for #{tshow api}
AvsStatusSearchEmpty: AVS returned no card information
AvsPersonSearchEmpty: AVS search returned empty result
AvsPersonSearchAmbiguous: AVS search returned more than one result
AvsSetLicencesFailed reason: Set driving licence within AVS failed. Reason: #{reason}
AvsIdMismatch api1 api2: AVS search for id #{tshow api1} returned id #{tshow api2} instead
AvsUserCreationFailed api@AvsPersonId: No new user could be created for AVS Id #{tshow api}, since an existing user shares at least one id presumed as unique
AvsCardsEmpty: AVS search returned no id cards
AvsCurrentData: All shown data has been recently received via the AVS interface.
AvsUpdateDayCheck: In addition, a background AVS update has been scheduled for all persons occrring within the day agenda (once per Day).
AvsNoApronCard: No valid card granting apron access found
AvsNoCompanyCard mcn@(Maybe CompanyName): No valid card for booking company #{maybeEmpty mcn ciOriginal} found

View File

@ -70,6 +70,10 @@ CourseInvalidInput: Eingaben bitte korrigieren.
CourseEditTitle: Kursart editieren/anlegen
CourseEditOk tid@TermId ssh@SchoolId csh@CourseShorthand: Kursart #{tid}-#{ssh}-#{csh} wurde erfolgreich geändert.
CourseEditDupShort tid@TermId ssh@SchoolId csh@CourseShorthand: Kursart #{tid}-#{ssh}-#{csh} konnte nicht geändert werden: Es gibt bereits einen andere Kursart mit dem selben Kürzel oder Titel in diesem Jahr und Bereich.
CourseEditQualificationFail: Eine Qualifikation konnte uas unbekanntem Grund nicht mit diesem Kurs assoziiert werden.
CourseEditQualificationFailRights qsh@QualificationShorthand ssh@SchoolId: Qualifikation #{qsh} konnte nicht mit diesem Kurs assoziiert werden, da Ihre Berechtigungen für Bereich #{ssh} dazu nicht ausreichen.
CourseEditQualificationFailExists: Diese Qualifikation ist bereits assoziiert
CourseEditQualificationFailOrder: Diese Sortierpriorität existiert bereits
CourseLecturer: Kursverwalter:in
MailSubjectParticipantInvitation tid@TermId ssh@SchoolId csh@CourseShorthand: [#{tid}-#{ssh}-#{csh}] Einladung zur Kursartteilnahme
CourseParticipantInviteHeading courseName@Text: Einladung zum Kursartteilnahmer für #{courseName}
@ -90,6 +94,8 @@ CourseParticipantsRegisterTutorialFieldTip: Ist aktuell keine Kurs mit diesem Na
CourseParticipantsRegisterNoneGiven: Es wurden keine anzumeldenden Personen angegeben!
CourseParticipantsRegisterNotFoundInAvs n@Int: Zu #{n} #{pluralDE n "Angabe konnte keine übereinstimmende Person" "Angaben konnten keine übereinstimmenden Personen"} im AVS gefunden werden
CourseParticipantsRegisterTutorialFirstDayTip: Wenn ein neuer Kurs gemäß einer Vorlage erstellt wird, werden die Zeiten gemäß dem Starttag angepasst
CourseParticipantsTutorialType: Typ der Vorlage
CourseParticipantsTutorialTypeTooltip: Ein neuer Kurs wird wie ein Kurs namens "Vorlage_[typ]" erstellt, wobei zuerst in der aktuellen Kursart, danach in Kursarten gleichen Namens und möglichst neuem Datum gesucht wird.
CourseParticipantsInvited n@Int: #{n} #{pluralDE n "Einladung" "Einladungen"} per E-Mail verschickt
CourseParticipantsAlreadyRegistered n@Int: #{n} #{pluralDE n "Teinehmer:in" "Teilnehmer:innen"} #{pluralDE n "ist" "sind"} bereits zur Kursart angemeldet
@ -131,6 +137,9 @@ CourseUserTutorialsDeregistered count@Int64: Teilnehmer:in von #{show count} #{p
CourseUserNoTutorialsDeregistered: Teilnehmer:in ist zu keinem der gewählten Kurse angemeldet
CourseUserTutorials: Angemeldete Kurse
CourseUserExams: Angemeldete Prüfungen
CourseUserExamOccurrences: Prüfungstermin
CourseUserExamOccurrenceOverride: Ggf. vorhandenen Prüfungstermin überschreiben
CourseUserExamOccurrenceAgainExaminer: Ggf. vorherige Prüfer erneut erlauben
CourseUserSheets: Übungsblätter
CsvColumnUserName: Voller Name des/der Teilnehmers/Teilnehmerin
CsvColumnUserMatriculation: AVS Nummer des/der Teilnehmers/Teilnehmerin
@ -235,7 +244,7 @@ UtilEditedBy name@Text time@Text: #{time} durch #{name}
CourseDate: Datum
MailSubjectLecturerInvitation tid@TermId ssh@SchoolId csh@CourseShorthand: [#{tid}-#{ssh}-#{csh}] Einladung als Kursverwalter:in
LecturerInvitationAccepted lType@Text csh@CourseShorthand: Sie wurden als #{lType} für #{csh} eingetragen
CourseExamRegistrationTime: Angemeldet seit
CourseExamRegistrationTime: Angemeldet am
CourseParticipantStateIsActiveFilter: Ansicht
CourseApply: Zur Kursart bewerben
CourseAdministrator: Kursadministrator:in

View File

@ -2,7 +2,7 @@
#
# SPDX-License-Identifier: AGPL-3.0-or-later
FilterCourse: Course
FilterCourse: Course category
FilterCourseShort: Shorthand
FilterTerm: Year
FilterCourseSchoolShort: Department
@ -15,7 +15,7 @@ FilterCourseRegisterOpen: Enrolment is allowed
CourseRegistered: Enrolled
CourseRegistration: Enrolment
CourseDescription: Description
CommCourseHeading: Course type message
CommCourseHeading: Course category message
CourseLecturers: Course administrators
CourseLecturerEmail: Email
CourseLecturerAlreadyAdded: This user is already configured as a course administrator
@ -25,12 +25,12 @@ CourseLecturerRightsIdentical: All sorts of course administrators have the same
CourseAcceptSubstitutesUntil: Accept substitute registrations until
CourseAcceptSubstitutesUntilTip: Until which time should substitute registrations through the central allocation be accepted to fill free places in the course? If left empty no substitute registrations will be made. This deadline should not arbitrarily be set early or ommitted so as to not be an unneccesarily restrictive for students. For a seminar a valid choice might be a few hours before the first meeting in which topics will be assigned.
CourseDeregisterNoShow: Record “no show” when deregistering
CourseDeregisterNoShowTip: Should “no show” be recorded as the exam achievement for all exams associated with this course type automatically whenever a course type participant deregisters themselves? This would be done once upon deregistration (if no other achievement exists for the given exam) and automatically whenever a new exam is created.
CourseDeregisterNoShowTip: Should “no show” be recorded as the exam achievement for all exams associated with this course category automatically whenever a course category participant deregisters themselves? This would be done once upon deregistration (if no other achievement exists for the given exam) and automatically whenever a new exam is created.
CourseSchool: Department
CourseSchoolMultipleTip: You may select from among multiple departments. Please ensure that you select the appropriate department for your course.
CourseName: Title
CourseShorthand: Shorthand
CourseShorthandUnique: Needs to be unique within school and year. Will be used verbatim within the url of the course type page.
CourseShorthandUnique: Needs to be unique within school and year. Will be used verbatim within the url of the course category page.
CourseSemester: Year
CourseDescriptionPlaceholder: Please include the module description
CourseHomepageExternalPlaceholder: Optional external URL
@ -38,14 +38,14 @@ CourseHomepageExternal: External homepage
CourseSemesterMultipleTip: You are currently allowed to select from among multiple years. Please ensure that you select the appropriate year for your course.
CourseVisibleFrom: Visible from
CourseVisibleTo: Visible to
CourseVisibleFromTip: The course type will be visible to others from this date onward. When left empty the course type will never be visible to other users. This does not affect course administrators, assistants, instructors, correctors, enrolled participants and applicants of/to this course. If the course type participates in a central allocation, the course type visibility will be forced during the application phase.
CourseVisibleToTip: Other users will be able to see the course type from "Visible From" up to this date. When left empty visible courses will remain visible indefinitely.
CourseMaterialFree: Course type material is publicly accessible
CourseVisibleFromTip: The course category will be visible to others from this date onward. When left empty the course category will never be visible to other users. This does not affect course administrators, assistants, instructors, correctors, enrolled participants and applicants of/to this course. If the course category participates in a central allocation, the course category visibility will be forced during the application phase.
CourseVisibleToTip: Other users will be able to see the course category from "Visible From" up to this date. When left empty visible courses will remain visible indefinitely.
CourseMaterialFree: Course category material is publicly accessible
CourseFormSectionRegistration: Registration
CourseFormSectionAdministration: Administration
CourseCapacity: Capacity
CourseCapacityTip: Maximum permissable number of enrolments for this course; leave empty for unlimited capacity
CourseSecretTip: Enrollment for this course type will require the password, if set
CourseSecretTip: Enrollment for this course category will require the password, if set
CourseSecretFormat: Arbitrary string
CourseSecretWrong: Wrong password
CourseSecret: Access password
@ -59,19 +59,23 @@ CourseVisibilityEndMustBeAfterStart: The end of the visibility period must be af
CourseRegistrationEndMustBeAfterStart: The end of the registration period must be after its start
CourseDeregistrationEndMustBeAfterStart: The end of the deregistration period must be after the start of the registration period
CourseUserMustBeLecturer: The current user needs to be a course administrator
CourseShorthandTooLong: Long course type shorthands may lead to display issues and might complicate communication with students. Please choose a more concise shorthand if possible.
CourseNotAlwaysVisibleDuringRegistration: To allow for students to register, the course type should also be visible during the entire registration period (which is currently not the case).
CourseShorthandTooLong: Long course category shorthands may lead to display issues and might complicate communication with students. Please choose a more concise shorthand if possible.
CourseNotAlwaysVisibleDuringRegistration: To allow for students to register, the course category should also be visible during the entire registration period (which is currently not the case).
NoSuchTerm tid: Year #{tid} does not exist.
NoSuchSchool ssh: Department #{ssh} does not exist.
NoSuchCourseShorthand csh: There is no course type with shorthand #{csh}.
NoSuchCourse: No such course type found.
CourseNewDupShort tid ssh csh: Could not create course type #{tid}-#{ssh}-#{csh}. Another course type with the same shorthand or title already exists for the given year and school.
NoSuchCourseShorthand csh: There is no course category with shorthand #{csh}.
NoSuchCourse: No such course category found.
CourseNewDupShort tid ssh csh: Could not create course category #{tid}-#{ssh}-#{csh}. Another course category with the same shorthand or title already exists for the given year and school.
CourseInvalidInput: Invalid input
CourseEditTitle: Edit/Create course
CourseEditOk tid ssh csh: Successfully edited course type #{tid}-#{ssh}-#{csh}
CourseEditDupShort tid ssh csh: Could not edit course type #{tid}-#{ssh}-#{csh}. Another course type with the same shorthand or title already exists for the given year and school.
CourseEditOk tid ssh csh: Successfully edited course category #{tid}-#{ssh}-#{csh}
CourseEditDupShort tid ssh csh: Could not edit course category #{tid}-#{ssh}-#{csh}. Another course category with the same shorthand or title already exists for the given year and school.
CourseEditQualificationFail: A qualifikation could not be associated with this course for unknown reasons.
CourseEditQualificationFailRights qsh ssh: Qualification #{qsh} could not be associated with this course, due to your insufficient rights for department #{ssh}.
CourseEditQualificationFailExists: This qualification is already associated
CourseEditQualificationFailOrder: This sort order priority is used already
CourseLecturer: Course administrator
MailSubjectParticipantInvitation tid@TermId ssh@SchoolId csh@CourseShorthand: [#{tid}-#{ssh}-#{csh}] Invitaion to join the course
MailSubjectParticipantInvitation tid ssh csh: [#{tid}-#{ssh}-#{csh}] Invitaion to join the course
CourseParticipantInviteHeading courseName: Invitation to enrol for #{courseName}
CourseParticipantInviteExplanation: You were invited to be a participant of a course.
CourseParticipantInviteField: Email addresses to invite
@ -79,21 +83,23 @@ CourseParticipantInvitationAccepted courseName: You were enrolled in #{courseNam
CourseParticipantEnlistDirectly: Enrol known users directly
CourseSubmissionGroup: Registered submission group
SubmissionGroupEmptyIsUnsetTip: Leave empty to remove users from their respective submission groups
CourseParticipantsRegisterHeading: Add course type participants
CourseParticipantsRegisterActionAddParticipants: Add course type participants
CourseParticipantsRegisterHeading: Add course category participants
CourseParticipantsRegisterActionAddParticipants: Add course category participants
CourseParticipantsRegisterActionAddTutorialMembers: Add course participants
CourseParticipantsRegisterUsersField: Persons to register for course
CourseParticipantsRegisterUsersFieldTip: Please enter id card no (including dot), Fraport personnel number or email. Please separate multiple entries with comma or space.
CourseParticipantsRegisterTutorialOption: Register course type participants for course?
CourseParticipantsRegisterTutorialOption: Register course category participants for course?
CourseParticipantsRegisterTutorialField: Course
CourseParticipantsRegisterTutorialFieldTip: If there is no course with this name, a new one will be created. If there is a course with this name, the course type participants will be registered for it.
CourseParticipantsRegisterTutorialFieldTip: If there is no course with this name, a new one will be created. If there is a course with this name, the course category participants will be registered for it.
CourseParticipantsRegisterNoneGiven: No persons given to register!
CourseParticipantsRegisterNotFoundInAvs n: For #{n} #{pluralEN n "entry no corresponding person" "entries no corresponding persons"} could be found in AVS
CourseParticipantsRegisterTutorialFirstDayTip: If a new course is created and a template exists, its dates are adjusted according to the start date
CourseParticipantsRegisterUnnecessary: All requested registrations have already been saved. No actions have been performed.
CourseParticipantsTutorialType: Template type
CourseParticipantsTutorialTypeTooltip: A new course creation copies a course named "Template_[typ]", preferably from the same course category or another having the same name, the most recent being preferred.
CourseParticipantsInvited n: #{n} #{pluralEN n "invitation" "invitations"} sent via email
CourseParticipantsAlreadyRegistered n: #{n} #{pluralEN n "participant is" "participants are"} already course type #{pluralEN n "member" "members"}
CourseParticipantsAlreadyRegistered n: #{n} #{pluralEN n "participant is" "participants are"} already course category #{pluralEN n "member" "members"}
CourseParticipantsAlreadyTutorialMember n: #{n} #{pluralEN n "participant is" "participants are"} already registered for this course
CourseParticipantsRegistered n: Successfully registered #{n} #{pluralEN n "participant" "participants"} for course
CourseParticipantsRegisteredTutorial n: Successfully registered #{n} #{pluralEN n "participant" "participants"} for course
@ -106,9 +112,9 @@ CourseRegistrationFiles: Registration file(s)
CourseRegistrationFilesNeedReupload: Registration files need to be reuploaded every time the registration is changed
CourseRegistrationFile: Registration file
CourseRegistrationArchive: Zip archive of registration files
CourseDeregistrationNoShow: If you deregister from this course type “no show” will be recorded as your exam achievement for all exams associated with this course. If you have good reasons why you shold not be held accountable for leaving the course, please contact a course administrator. Course administrators can deregister you without incurring a permanent record.
CourseDeregistrationFromInvisibleCourse: This course type is only visible to enrolled participants and applicants. If you deregister now, you will not be able to access the course type again!
CourseDeregistrationNoReRegistration: If you deregister from the course type now, you will not be able to re-register yourself.
CourseDeregistrationNoShow: If you deregister from this course category “no show” will be recorded as your exam achievement for all exams associated with this course. If you have good reasons why you shold not be held accountable for leaving the course, please contact a course administrator. Course administrators can deregister you without incurring a permanent record.
CourseDeregistrationFromInvisibleCourse: This course category is only visible to enrolled participants and applicants. If you deregister now, you will not be able to access the course category again!
CourseDeregistrationNoReRegistration: If you deregister from the course category now, you will not be able to re-register yourself.
LoginNecessary: Please log in first!
RegisterRetry: You haven't been enrolled. Press "Enrol for course" to enrol
CourseRegisterOk: Successfully enrolled for course
@ -131,6 +137,9 @@ CourseUserTutorialsDeregistered count: Sucessfully deregistered participant from
CourseUserNoTutorialsDeregistered: Participant is not registered for any of the selected courses
CourseUserTutorials: Registered courses
CourseUserExams: Registered exams
CourseUserExamOccurrences: Exam occurrence
CourseUserExamOccurrenceOverride: Override other registrations for this exam, if any
CourseUserExamOccurrenceAgainExaminer: Possibly allow previous examiners again
CourseUserSheets: Exercise sheets
CsvColumnUserName: Participant's full name
CsvColumnUserMatriculation: Participant's AVS number
@ -144,7 +153,7 @@ CsvColumnUserExam: Exams which the user is registered for, separated by semicolo
CsvColumnUserSubmissionGroup: Registered submission group
CsvColumnUserSurname: Participant's surname
CsvColumnUserFirstName: Participant's given name
CsvColumnUserNote: Course type notes for the participant
CsvColumnUserNote: Course category notes for the participant
CourseUserCsvName tid ssh csh: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase csh}-participants
CourseUserTutorial: Registered course
CourseUserExam: Registered exam
@ -171,21 +180,21 @@ AssistantsFor: Assistants
CourseAdminFor: Course administration
TutorsFor n: #{pluralENs n "Instructor" }
CorrectorsFor n: #{pluralEN n "Corrector" "Correctors"}
CourseParticipantsHeading: Course type participants
CourseParticipantsHeading: Course category participants
CourseParticipantsCount n: #{n}
CourseParticipantsCountOf n m: #{n} of #{m}
CourseVisibility: Visibility
CourseInvisible: This course type is currently only visible to course administrators, assistants, instructors, correctors, enrolled participants and applicants.
CourseInvisible: This course category is currently only visible to course administrators, assistants, instructors, correctors, enrolled participants and applicants.
CourseRegistrationInterval: Enrolment
CourseDirectRegistrationInterval: Direct enrolment
CourseDeregisterUntil time: Deregistration only until #{time}
NotRegistered: Note enrolled for this course
CourseMaterial: Material
CourseMaterialNotFree: Course type material is only accessible to members of the course, e.g. for participants, instructors, correctors or administratiors.
CourseMaterialsFoundHere: Material for this course type is available here
CourseMaterialsNoneVisible: Currently there is no material for this course type or only material to which you don't have access (e.g. because of visibility settings)
CourseSheetsFoundHere: Exercise sheets for this course type are available here
CourseSheetsNoneVisible: Currently there are no exercise sheets for this course type or only exercise sheets to which you don't have access (e.g. because of visibility settings)
CourseMaterialNotFree: Course category material is only accessible to members of the course, e.g. for participants, instructors, correctors or administratiors.
CourseMaterialsFoundHere: Material for this course category is available here
CourseMaterialsNoneVisible: Currently there is no material for this course category or only material to which you don't have access (e.g. because of visibility settings)
CourseSheetsFoundHere: Exercise sheets for this course category are available here
CourseSheetsNoneVisible: Currently there are no exercise sheets for this course category or only exercise sheets to which you don't have access (e.g. because of visibility settings)
SheetListCourse: Exercise sheets
CourseExams: Exams
CourseTutorials: Courses
@ -228,13 +237,13 @@ TutorialRegisterFrom: Register from
TutorialRegisterTo: Register to
CourseDeleteQuestion: Are you sure you want to delete the below-mentioned course?
CourseDeleted: Course type deleted
CourseDeleted: Course category deleted
UtilEditedBy name time: #{time} by #{name}
CourseDate: Date
MailSubjectLecturerInvitation tid ssh csh: [#{tid}-#{ssh}-#{csh}] Invitation to be a course administrator
LecturerInvitationAccepted lType csh: You were registered as #{lType} for #{csh}
CourseExamRegistrationTime: Registered since
CourseExamRegistrationTime: Registered on
CourseParticipantStateIsActiveFilter: View
CourseApply: Apply for course
CourseAdministrator: Course administrator

View File

@ -3,7 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
CourseEvents: Termine
CourseEventType: Art
CourseEventType: Kategorie
CourseEventTypePlaceholder: Vorlesung, Zentralübung, ...
CourseEventTime: Zeit
CourseEventRoom: Regulärer Raum

View File

@ -8,17 +8,17 @@ CourseEventTypePlaceholder: Lecture, Exercise discussion, ...
CourseEventTime: Time
CourseEventRoom: Regular room
CourseEventRoomHidden: Room only for participants
CourseEventRoomHiddenTip: Should the room only be displayde to course type participants?
CourseEventRoomHiddenTip: Should the room only be displayde to course category participants?
CourseEventRoomIsUnset: —
CourseEventRoomIsHidden: Room is only displayed to course type associated persons (participants, instructors, correctors, etc.)
CourseEventRoomIsHidden: Room is only displayed to course category associated persons (participants, instructors, correctors, etc.)
CourseEventNote: Note
CourseEventActions: Actions
CourseEventsActionEdit: Edit
CourseEventsActionDelete: Delete
CourseEventsActionCreate: New occurrence
CourseEventCreated: Successfully created course type occurrence
CourseEventEdited: Successfully edited course type occurrence
CourseEventDeleteQuestion: Are you sure you want to delete the course type occurrence mentioned below?
CourseEventDeleted: Successfully deleted course type occurrence
CourseEventEdit: Edit course type occurrence
CourseEventNew: New course type occurrence
CourseEventCreated: Successfully created course category occurrence
CourseEventEdited: Successfully edited course category occurrence
CourseEventDeleteQuestion: Are you sure you want to delete the course category occurrence mentioned below?
CourseEventDeleted: Successfully deleted course category occurrence
CourseEventEdit: Edit course category occurrence
CourseEventNew: New course category occurrence

View File

@ -9,17 +9,17 @@ CourseNewsLastEdited time: Last changed: #{time}
CourseNewsActionEdit: Edit
CourseNewsActionDelete: Delete
CourseNewsActionCreate: Create new item
CourseNewsVisibleFromEditWarning: This item of course type news has already been published and should no longer be changed sind this might confuse participants.
CourseNewsVisibleFromEditWarning: This item of course category news has already been published and should no longer be changed sind this might confuse participants.
CourseNewsVisibleFromTip: If left empty this item is never visible. Leave empty for unfinished items
CourseNewsTitle: Title
CourseNewsSummary: Summary
CourseNewsSummaryTip: If specified this only the summary will be shown on the course type page, saving space. The content will be shown in a popup
CourseNewsSummaryTip: If specified this only the summary will be shown on the course category page, saving space. The content will be shown in a popup
CourseNewsContent: Content
CourseNewsParticipantsOnly: Only for course type participants
CourseNewsParticipantsOnly: Only for course category participants
CourseNewsVisibleFrom: Visible from
CourseNewsCreated: Successfully created item of course type news
CourseNewsEdited: Successfully edited item of course type news
CourseNewsDeleteQuestion: Are you sure you want to delete the item of course type news listed below?
CourseNewsDeleted: Successfully deleted item of course type news
CourseNewsNew: Add course type news
CourseNewsEdit: Edit item of course type news
CourseNewsCreated: Successfully created item of course category news
CourseNewsEdited: Successfully edited item of course category news
CourseNewsDeleteQuestion: Are you sure you want to delete the item of course category news listed below?
CourseNewsDeleted: Successfully deleted item of course category news
CourseNewsNew: Add course category news
CourseNewsEdit: Edit item of course category news

View File

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2022 Gregor Kleen <gregor.kleen@ifi.lmu.de>,Sarah Vaupel <sarah.vaupel@ifi.lmu.de>,Winnie Ros <winnie.ros@campus.lmu.de>
# SPDX-FileCopyrightText: 2022-25 Gregor Kleen <gregor.kleen@ifi.lmu.de>,Sarah Vaupel <sarah.vaupel@ifi.lmu.de>,Winnie Ros <winnie.ros@campus.lmu.de>,Steffen Jost <s.jost@fraport.de>
#
# SPDX-License-Identifier: AGPL-3.0-or-later
@ -35,7 +35,7 @@ ExamEditHeading examn@ExamName: #{examn} bearbeiten
ExamNameTip: Muss innerhalb der Veranstaltung eindeutig sein
ExamDescription: Beschreibung
ExamFormTimes: Zeiten
ExamFormOccurrences: Prüfungstermine/Räume
ExamFormOccurrences: Prüfungstermine / Räume
ExamFormAutomaticFunctions: Automatische Funktionen
ExamFormCorrection: Korrektur
ExamFormParts: Teile
@ -43,12 +43,13 @@ ExamFormMode: Ausgestaltung der Prüfung
ExamFormGrades: Prüfungsleistungen
ExamStart: Beginn
ExamEnd: Ende
ExamTimeTip: Nur zur Information der Studierenden, die tatsächliche Zeitangabe erfolgt pro Prüfungstermin/Raum
ExamTimeTip: Nur zur Information, die tatsächliche Zeitangabe erfolgt pro Prüfungstermin/Raum.
ExamTimeFilterTip: In der Kursansicht für Kursverwaltende wird diese Zeit zur Filterung verwendet.
ExamVisibleFrom: Sichtbar ab
ExamVisibleFromTip: Ohne Datum nie sichtbar und keine Anmeldung möglich
ExamRegisterFrom: Anmeldung ab
ExamRegisterTo: Anmeldung bis
ExamRegisterFromTip: Zeitpunkt ab dem sich Kursartteilnehmer:innen selbständig zur Prüfung anmelden können; ohne Datum ist keine Anmeldung möglich
ExamRegisterFromTip: Zeitpunkt ab dem sich Kursartteilnehmer:innen selbständig zur Prüfung anmelden können; ohne Datum ist keine selbständige Anmeldung möglich
ExamDeregisterUntil: Abmeldung bis
ExamPublishOccurrenceAssignments: Termin- bzw. Raumzuteilung den Teilnehmer:innen mitteilen um
ExamPublishOccurrenceAssignmentsTip: Ab diesem Zeitpunkt können Teilnehmer:innen einsehen zu welcher Teilprüfung bzw. welchen Raum sie angemeldet sind
@ -64,14 +65,15 @@ ExamAutomaticGradingTip: Sollen die Gesamtleistungen der Teilnehmer:innen automa
ExamBonus: Bonuspunkte-System
ExamGradingMode: Bewertungsmodus
ExamGradingModeTip: In welcher Form werden Prüfungsleistungen für diese Prüfung eingetragen?
ExamStaff: Prüfer:innen/Verantwortliche Hochschullehrer:innen
ExamStaffTip: Geben Sie bitte in jedem Fall einen Namen an, der Prüfer:in/Veranstalter:in/Hochschullehrer:in eindeutig identifiziert! Sollte der Name des Prüfers/der Prüferin allein womöglich nicht eindeutig sein, so geben Sie bitte eindeutig identifizierende Zusatzinfos, wie beispielsweise den Lehrstuhl bzw. die LFE o.Ä., an.
ExamStaff: Hauptverantworliche:r
ExamStaffTip: Hauptverantwortliche:r Prüfer:in, Textfeld zur reinen Information der Teilnehmenden.
ExamExamOfficeSchools: Zusätzliche Bereiche
ExamExamOfficeSchoolsTip: Prüfungsbeauftragte von Bereichen, die Sie hier angeben, erhalten im System (zusätzlich zum primären Bereich der zugehörigen Kursart) volle Einsicht in sämtliche für diese Prüfung hinterlegten Leistungen, unabhängig von den Studiendaten der Teilnehmer:innen.
ExamCorrectorEmail: E-Mail
ExamCorrectors: Korrektor:innen
ExamCorrectorsTip: Hier eingetragene Korrektor:innen können zwischen Beginn der Prüfung und "Bewertung abgeschlossen ab" Ergebnisse für alle Teilprüfungen und alle Teilnehmer:innen im System hinterlegen.
ExamCorrectorAlreadyAdded: Ein Korrektor/eine Korrektorin mit dieser E-Mail ist bereits für diese Prüfung eingetragen
ExamCorrectors: Prüfer:innen
ExamCorrectorsTip: Hier eingetragene Prüfer:innen können zwischen Beginn der Prüfung und "Bewertung abgeschlossen ab" Ergebnisse für alle Teilprüfungen und alle Teilnehmer:innen im System hinterlegen.
ExamCorrectorAlreadyAdded: Ein Prüfer:innen mit dieser E-Mail ist bereits für diese Prüfung eingetragen
ExamParticipant: Prüfungsteilnehmer:in
ExamRoom: Raum
ExamRoomManual': Keine automatische bzw. selbstständige Zuteilung
ExamRoomSurname': Nach Nachname
@ -86,6 +88,7 @@ ExamRoomAlreadyExists: Prüfung ist bereits eingetragen
ExamRoomName: Interne Bezeichnung
ExamRoomCapacity: Kapazität
ExamRoomCapacityNegative: Kapazität darf nicht negativ sein
ExamRoomCapacityInsufficient n@Int: Kapazität reicht nicht aus, #{noneOneMoreDE n "keine Plätze" "nur noch ein Platz" ("nur noch " <> tshow n <> " Plätze")} verfügbar
ExamRoomTime: Termin
ExamRoomStart: Beginn
ExamRoomEnd: Ende
@ -123,6 +126,8 @@ ExamOccurrenceStartMustBeAfterExamStart eoName@ExamOccurrenceName: Beginn des Te
ExamOccurrenceEndMustBeBeforeExamEnd eoName@ExamOccurrenceName: Ende des Termins #{eoName} liegt nach dem Ende der Prüfung
ExamOccurrenceDuplicate eoRoom@Text eoRange@Text: Raum #{eoRoom}, Termin #{eoRange} kommt mehrfach mit der selben Beschreibung vor
ExamOccurrenceDuplicateName eoName@ExamOccurrenceName: Interne Terminbezeichnung #{eoName} kommt mehrfach vor
ExamOccurrenceExaminerIsUnset !ident-ok: —
ExamOccurrenceExaminerIsHidden: Prüfer wird nur Teilnehmer:innen angezeigt
ExamOccurrenceRoomIsUnset !ident-ok: —
ExamOccurrenceRoomIsHidden: Raum wird nur Teilnehmer:innen angezeigt
ExamOccurrenceCannotBeDeletedDueToRegistrations eoName@ExamOccurrenceName: Termin #{eoName} kann nicht gelöscht werden, da noch Teilnehmer:innen diesem Termin zugewiesen sind. Über die Liste von Prüfungsteilnehmern können Sie zunächst die entsprechenden Terminzuweisungen entfernen.
@ -217,6 +222,13 @@ ExamOccurrenceRuleParticipant: Termin- bzw. Raumzuteilungsverfahren
ExamRegisteredCount: Anmeldungen
ExamRegisteredCountOf num@Int64 count@Int64 !ident-ok: #{num}/#{count}
ExamOccurrences: Termine
ExamOccurrencesCopied num@Int: #{pluralDEeN num "Prüfungstermin"} kopiert
ExamOccurrencesEdited num@Int del@Int: #{pluralENsN num "Prüfungstermin"} geändert #{guardMonoid (del > 0) ("und " <> pluralENsN num "Prüfungstermin" <> " gelöscht")}
ExamOccurrenceCopyNoStartDate: Dieser Kurs hat noch keine eigene Termine um Prüfungstermine zeitlich damit zu assoziieren
ExamOccurrenceCopyFail: Keine passenden Prüfungstermine zum Kopieren gefunden
ExaminerReocurrence examiner@Text: Mehrfache Prüfung durch #{examiner}!
ExamProblemReoccurrence: Prüfungen mit wiederholt gleichem Prüfer
ExamNoProblemReoccurrence: Heute keine Prüfungen mit wiederholtem Prüfer.
GradingFrom: Ab
ExamNoShow: Nicht erschienen
ExamVoided: Entwertet
@ -264,6 +276,7 @@ ExamAutoOccurrenceExceptionRoomTooSmall: Automatische Verteilung gescheitert. Ei
ExamBonusInfoPoints: Zur Berechnung von Bonuspunkten werden nur jene Blätter herangezogen, deren Aktivitätszeitraum vor Start des jeweiligen Termin/Prüfung begonnen hat
ExamUserCsvSheetName tid@TermId ssh@SchoolId csh@CourseShorthand examn@ExamName: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase csh}-#{foldedCase examn} Teilnehmer
ExamRoomExaminerTip: Nur bereits eingetragene Prüfer:innen sind hier erlaubt
ExamRoomCapacityTip: Maximale Anzahl an Prüfungsteilnehmern für diesen Termin/Raum; leer lassen für unbeschränkte Teilnehmeranzahl
ExamRoomMappingRandom: Verteilung
ExamFinishHeading: Prüfungsergebnisse sichtbar schalten

View File

@ -1,11 +1,11 @@
# SPDX-FileCopyrightText: 2022 Gregor Kleen <gregor.kleen@ifi.lmu.de>,Sarah Vaupel <sarah.vaupel@ifi.lmu.de>,Winnie Ros <winnie.ros@campus.lmu.de>
# SPDX-FileCopyrightText: 2022-25 Gregor Kleen <gregor.kleen@ifi.lmu.de>,Sarah Vaupel <sarah.vaupel@ifi.lmu.de>,Winnie Ros <winnie.ros@campus.lmu.de>,Steffen Jost <s.jost@fraport.de>
#
# SPDX-License-Identifier: AGPL-3.0-or-later
ExamRegistrationInviteDeadline: Invitation valid until
ExamRegistrationEnlistDirectly: Register known users directly
ExamRegistrationEnlistDirectlyTip: Should users whose email addresses are known to the system be registered for the exam directly? Otherwise invitations will be sent to alle users, which they will have to accept first in order to be registered. Unknown users always receive an invitation.
ExamRegistrationRegisterCourse: Also enroll users in course type
ExamRegistrationRegisterCourse: Also enroll users in course category
ExamRegistrationRegisterCourseTip: Users that aren't enrolled already won't be registered for the exam otherwise.
ExamRegistrationInviteField: Email addresses
ExamParticipantsRegisterHeading: Add exam participants
@ -35,7 +35,7 @@ ExamEditHeading examn: Edit #{examn}
ExamNameTip: Needs to be unique within the course
ExamDescription: Description
ExamFormTimes: Times
ExamFormOccurrences: Occurrences/rooms
ExamFormOccurrences: Occurrences / Rooms
ExamFormAutomaticFunctions: Automatic functions
ExamFormCorrection: Correction
ExamFormParts: Exam parts
@ -43,12 +43,13 @@ ExamFormMode: Exam design
ExamFormGrades: Exam achievements
ExamStart: Start
ExamEnd: End
ExamTimeTip: Only for informational purposes. The actual times are set for each occurrence/room
ExamTimeTip: Only for informational purposes. The actual times are set for each occurrence/room.
ExamTimeFilterTip: Also used for Filtering in the course administrator course view.
ExamVisibleFrom: Visible from
ExamVisibleFromTip: If left empty the exam is never visible and course type participants may not register.
ExamVisibleFromTip: If left empty the exam is never visible and course category participants may not register.
ExamRegisterFrom: Register from
ExamRegisterTo: Register to
ExamRegisterFromTip: Start of the period in which course type participants may register themselves for the exam. If left empty participants are never allowed to register.
ExamRegisterFromTip: Start of the period in which course category participants may register themselves for the exam. If left empty participants are never allowed to register themselves.
ExamDeregisterUntil: Deregister until
ExamPublishOccurrenceAssignments: Publish occurrence/room-assignments
ExamPublishOccurrenceAssignmentsTip: At this time participants can find out to which occurrence/room they are assigned
@ -64,14 +65,15 @@ ExamAutomaticGradingTip: Should the exam achievement be automatically computed f
ExamBonus: Bonus point system
ExamGradingMode: Grading mode
ExamGradingModeTip: In which format should grades for this exam be entered?
ExamStaff: Examiner/Responsible university teacher
ExamStaffTip: Please always specify a name that uniquely identifies the examiner/organiser/repsonsible university teacher! If there is a possibility that the name alone is ambiguous please also specify some additional information e.g. the professorial chair or the educational and research unit.
ExamStaff: Chief examiner
ExamStaffTip: Primary responsible examiner, arbirary text field for pure informational purposes.
ExamExamOfficeSchools: Additional departments
ExamExamOfficeSchoolsTip: Exam offices of departments you specify here will also have full access to all results for this exam disregarding the individual participants' features of study.
ExamCorrectorEmail: Email
ExamCorrectors: Correctors
ExamCorrectorsTip: Correctors configured here may, after the start of the exam and until "Results visible from", enter exam part results for all exam parts and participants.
ExamCorrectorAlreadyAdded: A corrector with this email address already exists
ExamCorrectors: Examiner
ExamCorrectorsTip: Examiners configured here may, after the start of the exam and until "Results visible from", enter exam part results for all exam parts and participants.
ExamCorrectorAlreadyAdded: An examiner with this email address already exists
ExamParticipant: Examinee
ExamRoom: Room
ExamRoomManual': No automatic or autonomous assignment
ExamRoomSurname': By surname
@ -86,6 +88,7 @@ ExamRoomAlreadyExists: Occurrence already configured
ExamRoomName: Internal name
ExamRoomCapacity: Capacity
ExamRoomCapacityNegative: Capacity may not be negative
ExamRoomCapacityInsufficient n@Int: Insufficient capacity, #{noneOneMoreEN n "none" "just one" ("only " <> tshow n)} remaining
ExamRoomTime: Time
ExamRoomStart: Start
ExamRoomEnd: End
@ -123,8 +126,10 @@ ExamOccurrenceStartMustBeAfterExamStart eoName: Start of the occurrence #{eoName
ExamOccurrenceEndMustBeBeforeExamEnd eoName: End of the occurrence #{eoName} must be before the exam end
ExamOccurrenceDuplicate eoRoom eoRange: Combination of room #{eoRoom} and occurrence #{eoRange} occurs multiple times
ExamOccurrenceDuplicateName eoName: Internal name #{eoName} occurs multiple times
ExamOccurrenceExaminerIsUnset !ident-ok: —
ExamOccurrenceExaminerIsHidden: Examiner only displayed to participants registered for this occurrence
ExamOccurrenceRoomIsUnset: —
ExamOccurrenceRoomIsHidden: Room is only displayed to participants registered for this occurrence/room
ExamOccurrenceRoomIsHidden: Room only displayed to participants registered for this occurrence
ExamOccurrenceCannotBeDeletedDueToRegistrations eoName: Occurrence #{eoName} cannot be deleted because participants are registered for it. You can remove the offending registrations via the list of exam participants.
ExamRegistrationMustFollowSchoolSeparationFromStart dayCount: As per school rules there #{pluralEN dayCount "needs" "need"} to be at least #{dayCount} #{pluralEN dayCount "day" "days"} between "Register from" and "Start".
ExamRegistrationMustFollowSchoolDuration dayCount: As per school rules there #{pluralEN dayCount "needs" "need"} to be at least #{dayCount} #{pluralEN dayCount "day" "days"} between "Register from" and "Register to".
@ -159,7 +164,7 @@ CsvColumnExamUserExercisePassesMax: Maximum number of exercise sheets the partic
CsvColumnExamUserBonus: Exam bonus points
CsvColumnExamUserParts: Number of points the participant achieved per exam part. One column per exam part if applicable.
CsvColumnExamUserResult: Exam achievement; "passed", "failed", "no-show", "voided", or any number grade ("1.0", "1.3", "1.7", ..., "4.0", "5.0")
CsvColumnExamUserCourseNote: Course type notes for the participant
CsvColumnExamUserCourseNote: Course category notes for the participant
CsvColumnExamOfficeExamUserOccurrenceStart: Exam occurrence (ISO 8601)
CsvColumnUserStudyFeatures: All relevant features of study for the participant, separated by semicolon (;)
ExamUserCsvName tid ssh csh examn: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase csh}-#{foldedCase examn}-participants
@ -176,7 +181,7 @@ ExamAction: Action
ExamUsersExamDataRequiresRegistration: If exam data (part-/result, occurrence/room, bonus) is to be modified/set, the relenvant participant needs to be registered for the exam.
ExamNoOccurrence: No occurrence/room
ExamBonusNone: No bonus points
ExamUserCsvCourseNoteDeleted: Course type note will be deleted
ExamUserCsvCourseNoteDeleted: Course category note will be deleted
ExamUsersDeregistered count: Successfully deregistered #{show count} #{pluralEN count "participant" "participants"}
ExamUsersOccurrenceUpdated count: Successfully assigned occurrence/room for #{show count} #{pluralEN count "participant" "participants"}
ExamUsersResultsAccepted count: Successfully accepted computed result for #{show count} #{pluralEN count "participant" "participants"}
@ -217,6 +222,13 @@ ExamOccurrenceRuleParticipant: Occurrence/room assignment procedure
ExamRegisteredCount: Registrations
ExamRegisteredCountOf num count: #{num}/#{count}
ExamOccurrences: Exams
ExamOccurrencesCopied num: #{pluralENsN num "exam occurrence"} copied
ExamOccurrencesEdited num del: #{pluralENsN num "exam occurrence"} edited #{guardMonoid (del > 0) ("and " <> pluralENsN num "exam occurrence" <> " deleted")}
ExamOccurrenceCopyNoStartDate: This course needs its own occurrence to copy associated exam occurrences.
ExamOccurrenceCopyFail: No suitable exam occurrences found to copy from.
ExaminerReocurrence examiner: Multiple examinations by #{examiner}!
ExamProblemReoccurrence: Exams with reoccurring examiner
ExamNoProblemReoccurrence: Today there are no exams with a reoccurring examiner.
GradingFrom: From
#templates widgets/bonus-rule
@ -262,6 +274,8 @@ ExamAutoOccurrenceExceptionNoUsers: No participants can be distributed with the
ExamAutoOccurrenceExceptionRoomTooSmall: Automatic distribution failed. A different distribution procedure might succeed. Alternatively, minimizing rooms or removing small rooms might help.
ExamBonusInfoPoints: When calculating an exam bonus only those sheets will be considered, for which the submission period started before the start of the relevant occurrence/room
ExamUserCsvSheetName tid ssh csh examn: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase csh}-#{foldedCase examn} Participants
ExamRoomExaminerTip: Only examiners allowed here, add beforehand
ExamRoomCapacityTip: Maximum number of participants for this occurrence/room; leave empty for unlimited capacity
ExamRoomMappingRandom: Distribution
ExamFinishHeading: Make results visible
@ -302,9 +316,9 @@ ExamUserCsvOverrideResult: Override exam result in contradiction of computed val
ExamUserCsvSetBonus: Set bonus points
ExamUserCsvSetResult: Set exam result
ExamUserCsvSetPartResult: Set result for exam part
ExamUserCsvSetCourseNote: Modify course type participant notes
ExamUserCsvExceptionNoMatchingUser: Course type participant could not be identified uniquely. All identifiers (given name(s), surname, display name, matriculation, ..) must match exactly. You can try to remove some of the identifiers for the given line (i.e. all but matriculation). Uni2work will then search for users using only the remaining identifiers. In this case special care should be taken that Uni2work correctly identifies the intended user.
ExamUserCsvExceptionMultipleMatchingUsers: Course type participant could not be identified uniquely. There are multiple users that match the given identifiers. You can try to add more identifiers for the given line to ensure that only the intended user can be identified with them.
ExamUserCsvSetCourseNote: Modify course category participant notes
ExamUserCsvExceptionNoMatchingUser: Course category participant could not be identified uniquely. All identifiers (given name(s), surname, display name, matriculation, ..) must match exactly. You can try to remove some of the identifiers for the given line (i.e. all but matriculation). Uni2work will then search for users using only the remaining identifiers. In this case special care should be taken that Uni2work correctly identifies the intended user.
ExamUserCsvExceptionMultipleMatchingUsers: Course category participant could not be identified uniquely. There are multiple users that match the given identifiers. You can try to add more identifiers for the given line to ensure that only the intended user can be identified with them.
ExamUserCsvExceptionNoMatchingStudyFeatures: The specified field did not match with any of the participant's fields of study. You can try to remove the field of study for the given line. Uni2work will then automatically choose a field of study.
ExamUserCsvExceptionNoMatchingOccurrence: Occurrence/room could not be identified uniquely. Please ensure that the given line only contains internal room identifiers exactly as they have been configured for this exam.
ExamUserCsvExceptionMismatchedGradingMode expectedGradingMode actualGradingMode: The imported data contained an exam achievement which does not match the grading mode for this exam. The expected grading mode can be changed at "Edit exam" ("Passed/Failed", "Numeric grades", or "Mixed").

View File

@ -15,8 +15,8 @@ ExternalExamCorrectErrorNeedleTooShort: This identifier is too short.
UnauthorizedExternalExamCorrectorGrade: You may not enter overall exam achievements for this exam.
ExternalExamCorrectErrorMultipleMatchingUsers: This identifier matches on multiple students.
ExternalExamCorrectErrorNoMatchingUsers: This identifier does not match any student.
ExternalExamEdited coursen@CourseName examn@ExamName: Succesfully edited exam “#{examn}” for course type “#{coursen}”.
ExternalExamExists coursen@CourseName examn@ExamName: Exam “#{examn}” already exists for course type “#{coursen}”.
ExternalExamEdited coursen@CourseName examn@ExamName: Succesfully edited exam “#{examn}” for course category “#{coursen}”.
ExternalExamExists coursen@CourseName examn@ExamName: Exam “#{examn}” already exists for course category “#{coursen}”.
ExternalExamEdit coursen examn: Edit: #{coursen}, #{examn}
ExternalExamSemester: Year
ExternalExamSchool: Department
@ -41,10 +41,10 @@ ExternalExamStaffTip: The list of ssociated persons is shown to exam offices and
ExternalExamStaffAlreadyAdded: Person is already associated with the exam.
ExternalExamStaffEmail: Email
ExternalExamUserMustBeStaff: You yourself must always be an associated person for exams you create.
ExternalExamCourseExists: This course type already exists with FRADrive. Exams for courses that exist within FRADrive should be associated with the course type directly instead of being created as an external exam.
ExternalExamCourseExists: This course category already exists with FRADrive. Exams for courses that exist within FRADrive should be associated with the course category directly instead of being created as an external exam.
HeadingExternalExamList: External exams
HeadingExternalExamNew: New external exam
ExternalExamCreated coursen@CourseName examn@ExamName: Succesfully created exam “#{examn}” for course type “#{coursen}”.
ExternalExamCreated coursen@CourseName examn@ExamName: Succesfully created exam “#{examn}” for course category “#{coursen}”.
MailSubjectExternalExamStaffInvitation coursen examn: Invitation to act as examiner for “#{examn}” of “#{coursen}”
ExternalExamOccurrenceEdited count: Successfully edited #{count} #{pluralEN count "occurrence" "occurrences"}
ExternalExamResultEdited count: Successfully edited #{count} #{pluralEN count "exam result" "exam results"}

View File

@ -4,7 +4,7 @@
MaterialList !ident-ok: Material
MaterialName !ident-ok: Name
MaterialType: Art
MaterialType: Typ
MaterialTypePlaceholder: Folien, Code, Beispiel, ...
MaterialTypeSlides: Folien
MaterialTypeCode !ident-ok: Code

View File

@ -11,27 +11,27 @@ MaterialTypeCode: Code
MaterialTypeExample: Example
MaterialDescription: Description
MaterialVisibleFrom: Visible to participants from
MaterialVisibleFromTip: Never visible to participants if left empty; leaving the date empty is only sensible for unfinished course type material or when course type material should be provided only to sheet correctors
MaterialVisibleFromEditWarning: This course type material has already been published and should not be edited. Doing so might confuse the participants.
MaterialInvisible: This course type material is currently invisible to participants!
MaterialVisibleFromTip: Never visible to participants if left empty; leaving the date empty is only sensible for unfinished course category material or when course category material should be provided only to sheet correctors
MaterialVisibleFromEditWarning: This course category material has already been published and should not be edited. Doing so might confuse the participants.
MaterialInvisible: This course category material is currently invisible to participants!
MaterialFiles: Files
MaterialHeading materialName: #{materialName}
MaterialListHeading: Course type materials
MaterialNewHeading: Publish new course type material
MaterialNewTitle: New course type material
MaterialEditHeading materialName: Edit course type material “#{materialName}”
MaterialEditTitle materialName: Edit course type material “#{materialName}”
MaterialSaveOk tid ssh csh materialName: Successfully saved “#{materialName}” for course type #{tid}-#{ssh}-#{csh}
MaterialNameDup tid ssh csh materialName: Course type material with the name “#{materialName}” already exists for course type #{tid}-#{ssh}-#{csh}
MaterialDeleteCaption: Do you really want to delete the course type material mentioned below?
MaterialListHeading: Course category materials
MaterialNewHeading: Publish new course category material
MaterialNewTitle: New course category material
MaterialEditHeading materialName: Edit course category material “#{materialName}”
MaterialEditTitle materialName: Edit course category material “#{materialName}”
MaterialSaveOk tid ssh csh materialName: Successfully saved “#{materialName}” for course category #{tid}-#{ssh}-#{csh}
MaterialNameDup tid ssh csh materialName: Course category material with the name “#{materialName}” already exists for course category #{tid}-#{ssh}-#{csh}
MaterialDeleteCaption: Do you really want to delete the course category material mentioned below?
MaterialDelHasFiles count: including #{count} #{pluralEN count "file" "files"}
MaterialIsVisible: Caution, this course type material has already been published.
MaterialDeleted materialName: Successfully deleted course type material “#{materialName}”
MaterialIsVisible: Caution, this course category material has already been published.
MaterialDeleted materialName: Successfully deleted course category material “#{materialName}”
MaterialArchiveName tid ssh csh materialName: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase csh}-#{foldedCase materialName}
MaterialVideo materialName: #{materialName} - Video
MaterialVideoUnsupported: Your browser does not seem to support embedded video
MaterialVideoDownload: Download
MaterialFree: Course type material is publicly available.
MaterialFree: Course category material is publicly available.
AccessibleSince: Accessible since
VisibleFrom: Published
FilterMaterialNameSearch !ident-ok: Name

View File

@ -2,16 +2,16 @@
#
# SPDX-License-Identifier: AGPL-3.0-or-later
ParticipantsList: Lists of course type participants
ParticipantsIntersect: Common course type participants
ParticipantsList: Lists of course category participants
ParticipantsIntersect: Common course category participants
ParticipantsCsvName tid ssh: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-participants
ParticipantsIntersectCourseOption tid@TermId ssh@SchoolId coursen@CourseName: #{tid} - #{ssh} - #{coursen}
ParticipantsIntersectCourses: Courses
CourseParticipantsRegisteredWithoutField n: #{n} #{pluralEN n "participant was" "participants were"} registered without #{pluralEN n "an associated field of study" "associated fields of study"}, because #{pluralEN n "it" "they"} could not be determined uniquely.
ParticipantsCsvSheetName tid ssh: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)} Participants
CourseParticipants n: Currently #{n} course type #{pluralEN n "participant" "participants"}
CourseParticipants n: Currently #{n} course category #{pluralEN n "participant" "participants"}
ParticipantsIntersectNotOne: Intersection
AllUsersUnion: Union of all participants
AllUsersIntersection: Intersection of all participants
CourseDeleteActiveParticipants: This course type still has active participants. Remove all active participants first if you really want to delete this course.
CourseDeleteExistExams: This course type cannot be deleted, for as long as associated exams exist.
CourseDeleteActiveParticipants: This course category still has active participants. Remove all active participants first if you really want to delete this course.
CourseDeleteExistExams: This course category cannot be deleted, for as long as associated exams exist.

View File

@ -13,8 +13,8 @@ SheetDeleteQuestion: Do you really want to delete the below-mentioned exercise s
SheetDeleted: Successfully deleted exercise sheet
SheetArchiveName tid ssh csh shn: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase csh}-#{foldedCase shn}
SheetTypeArchiveName tid ssh csh shn renderedSft: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase csh}-#{foldedCase shn}-#{foldCase renderedSft}
SheetEditOk tid ssh csh sheetName: Successfully saved exercise sheet #{sheetName} in course type #{tid}-#{ssh}-#{csh}
SheetNameDup tid ssh csh sheetName: There already is an exercise sheet #{sheetName} in course type #{tid}-#{ssh}-#{csh}
SheetEditOk tid ssh csh sheetName: Successfully saved exercise sheet #{sheetName} in course category #{tid}-#{ssh}-#{csh}
SheetNameDup tid ssh csh sheetName: There already is an exercise sheet #{sheetName} in course category #{tid}-#{ssh}-#{csh}
SheetVisibleFrom: Visible from (for participants)
SheetVisibleFromTip: Always invisible for participants and no submission possible if left empty; only leave this field empty for temporary/unfinished sheets
SheetActiveFrom: Active from/Submission period start
@ -24,7 +24,7 @@ SheetSolutionFromTip: Always invisible for participants if left empty; corrector
SheetName: Name
SheetDescription: Description
SheetRequireExam: Require registration for an exam?
SheetRequireExamTip: If registration for an exam is required, only course type participants that are registered for that exam at the time of submission will be allowed to create submission. Download of sheet files will also be restricted to course type participants registered for the exam.
SheetRequireExamTip: If registration for an exam is required, only course category participants that are registered for that exam at the time of submission will be allowed to create submission. Download of sheet files will also be restricted to course category participants registered for the exam.
SheetRequiredExam: Exam
SheetFormType: Valuation & submission
SheetFormTimes: Times
@ -37,15 +37,15 @@ SheetMarkingFiles: Correction
SheetMarkingTip: Instructions for correction, visible only to correctors
SheetPersonalisedFilesDownload: Download personalised sheet files
SheetPersonalisedFiles: Personalised sheet files
SheetPersonalisedFilesTip: Should course type participants be assigned personalised sheet files in addition to the files configured above? Only the user to which a file has been assigned may view it.
SheetPersonalisedFilesTip: Should course category participants be assigned personalised sheet files in addition to the files configured above? Only the user to which a file has been assigned may view it.
SheetPersonalisedFilesUpload: Personalised sheet files
SheetPersonalisedFilesUploadTip: Download the template for a ZIP-archive of personalised sheet files, move files into the directories corresponding to the desired users and upload the archive again. If the name of a personalised file matches the name of an unpersonalised file, the personalised file replaces the unpersonalised one from the respective participants' point of view.
SheetPersonalisedFilesKeepExisting: Keep existing files
SheetPersonalisedFilesKeepExistingTip: Should the personalised files you upload be added to the already existing ones, if applicable? Otherwise the files you upload will completely replace any existing files.
SheetPersonalisedFilesAllowNonPersonalisedSubmission: Allow non-personalised submission
SheetPersonalisedFilesAllowNonPersonalisedSubmissionTip: Should course type participants with no assigned personalised files be allowed to submit anyway?
SheetPersonalisedFilesAllowNonPersonalisedSubmissionTip: Should course category participants with no assigned personalised files be allowed to submit anyway?
SheetPersonalisedFilesDownloadTemplateHere: You can download a template for a ZIP-archive of personalised sheet files with the structure that Uni2work expects here:
SheetPersonalisedFilesUsersList: List of course type participants who have personalised sheet files
SheetPersonalisedFilesUsersList: List of course category participants who have personalised sheet files
SheetPersonalisedFilesMetaYAMLSeedComment: This string was generated cryptographically from data uniquely identifying the user and exercise sheet. You can use it as a seed for a pseudorandom generator for generating (parts of) the personalised files.
SheetPersonalisedFilesMetaYAMLNoSeedComment: There is not enough information available to generate a seed. You will have to create the exercise sheet in Uni2work first. Once seeds can be generated they will be generated cryptographically and you may use them to generate (parts of) the personalised files.
SheetActiveFromTip: The exercise sheet's assignment will only be available for download and submission starting at this time. If left empty no submission or download of assignment is ever allowed
@ -63,7 +63,7 @@ SheetErrDeadlineEarly: "Submission period end" must be after "Submission period
SheetErrHintEarly: "Hint from" must be after "Submission period start"
SheetErrSolutionEarly: "Solution from" must be after "Submission period end"
SheetErrVisibleWithoutActive: If “Visible from (for participants)” is specified “Active from/Submission period start” must also be specified
SheetSubmissionModeNoneWithoutNotGraded: The sheet was configured to be "No submission" but not "Not marked". Course type participants will not be able to submit.
SheetSubmissionModeNoneWithoutNotGraded: The sheet was configured to be "No submission" but not "Not marked". Course category participants will not be able to submit.
SheetWarnNoActiveTo: “Active to/Submission period end” should always be specified
CountTutProp: Courses count against proportion
CountTutPropTip: If submissions are assigned by course, do those assignments count with regard to the set proportion?
@ -82,13 +82,13 @@ RatingPercent: Achieved
IsRated: Marked
SheetTypeIsExam: Rating „as an exam part“
SheetGradingSummaryTitle intgr: #{intgr} #{pluralEN intgr "sheet" "sheets"}
PersonalisedSheetFilesIgnored count: #{count} uploaded #{pluralEN count "file was" "files were"} ignored because #{pluralEN count "it" "they"} could not be associated with both a sheet file type and a course type participant.
PersonalisedSheetFilesIgnored count: #{count} uploaded #{pluralEN count "file was" "files were"} ignored because #{pluralEN count "it" "they"} could not be associated with both a sheet file type and a course category participant.
PersonalisedSheetFilesIgnoredIntro: The following files were ignored:
PersonalisedSheetFilesDownloadRestrictByExamNone: No restriction
PersonalisedSheetFilesDownloadRestrictByExam: Restrict to exam participants
PersonalisedSheetFilesDownloadRestrictByExamTip: Only download personalised sheet files for participants also registered to a certain exam?
PersonalisedSheetFilesDownloadAnonymousField: Anonymisation
PersonalisedSheetFilesDownloadAnonymousFieldTip: Should the ZIP-archive of personalised files be anonymised (it would then contain no immediately identifiable information regard the course type participants) or should directory names be decorated with an identifiable feature of the user and the files of meta information contain additional personal data?
PersonalisedSheetFilesDownloadAnonymousFieldTip: Should the ZIP-archive of personalised files be anonymised (it would then contain no immediately identifiable information regard the course category participants) or should directory names be decorated with an identifiable feature of the user and the files of meta information contain additional personal data?
PersonalisedSheetFilesMetaFilename uid: meta-information_#{toPathPiece uid}.yaml
PersonalisedSheetFilesArchiveName tid ssh csh shn: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase csh}-#{foldedCase shn}-personalised_files
SheetGeneratePseudonym: Generate

View File

@ -49,10 +49,10 @@ SubmissionArchive: Zip-archive of submission files
SubmissionArchiveCorrected: Zip-archive of submission files including corrections
SubmissionFile: Submission file
SubmissionFiles: Submitted files
EmailInvitationWarningPrevCoSubmittors: This address could not be matched to any course type participant with whom you have submitted for this course type before. An Invitation will be sent via email.
EmailInvitationWarningCourseParticipants: This address coulde not be matched to any course type participant. An Invitation will be sent via email.
MultiUserFieldExplanationPrevCoSubmittors: This input searches through the addresses of all course type participants for whom it could be determined, that you have already submitted with that person for this course.
MultiUserFieldExplanationCourseParticipants: This input searches through the addresses of all course type participants.
EmailInvitationWarningPrevCoSubmittors: This address could not be matched to any course category participant with whom you have submitted for this course category before. An Invitation will be sent via email.
EmailInvitationWarningCourseParticipants: This address coulde not be matched to any course category participant. An Invitation will be sent via email.
MultiUserFieldExplanationPrevCoSubmittors: This input searches through the addresses of all course category participants for whom it could be determined, that you have already submitted with that person for this course.
MultiUserFieldExplanationCourseParticipants: This input searches through the addresses of all course category participants.
SubmissionAlreadyExistsFor email: #{email} already has a submission for this sheet.
SubmissionUsersEmpty: Submissions may not be created without submittors.
SubmissionUserAlreadyAdded: This user is already configured as a submittor
@ -155,7 +155,7 @@ SubmissionSomeUsersDuplicateWarning: Some submittors are also submittors for a d
EMailUnknown email: Email #{email} does not belong to any known user.
CorDeficitProportion: Deficit (proportion)
CosubmittorTip: Invitations are sent via email to exactly those addresses for which it cannot be determined, that you have already submitted for this course type with the associated person, at least once. If one of the specified addresses can be matched to a person with whom you have submitted at least once for this course type already, the name of that person will be shown and the submission will immediately be made in their name as well.
CosubmittorTip: Invitations are sent via email to exactly those addresses for which it cannot be determined, that you have already submitted for this course category with the associated person, at least once. If one of the specified addresses can be matched to a person with whom you have submitted at least once for this course category already, the name of that person will be shown and the submission will immediately be made in their name as well.
CorrDownload: Download
SubmissionDownloadAnonymous: Anonymized
SubmissionDownloadSurnames: With surnames
@ -237,9 +237,9 @@ SubmissionFilterAuthorshipStatementCurrent: Current wording
SubmissionNoUsers: This submission has no associated users!
CsvColumnCorrectionTerm: Term of the course type of the submission
CsvColumnCorrectionSchool: School of the course type of the submission
CsvColumnCorrectionCourse: Shorthand of the course type of the submission
CsvColumnCorrectionTerm: Term of the course category of the submission
CsvColumnCorrectionSchool: School of the course category of the submission
CsvColumnCorrectionCourse: Shorthand of the course category of the submission
CsvColumnCorrectionSheet: Name of the sheet of the submission
CsvColumnCorrectionSubmission: Number of the submission (uwa…)
CsvColumnCorrectionSurname: Submittor's surnames, separated by semicolon (;)

View File

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2022 Winnie Ros <winnie.ros@campus.lmu.de>
# SPDX-FileCopyrightText: 2022-25 Winnie Ros <winnie.ros@campus.lmu.de>,Steffen Jost <s.jost@fraport.de>
#
# SPDX-License-Identifier: AGPL-3.0-or-later
@ -36,6 +36,7 @@ TutorialDelete: Löschen
TutorialsHeading: Kurse
TutorialNew: Neuer Kurs
TutorialRegisteredSuccess tutn@TutorialName: Erfolgreich zum Kurs #{tutn} angemeldet
TutorialRegisteredFail tutn@TutorialName: Anmeldung zum Kurs #{tutn} fehlgeschlagen. Existiert bereits eine Anmeldung?
TutorialDeregisteredSuccess tutn@TutorialName: Erfolgreich vom Kurs #{tutn} abgemeldet
MailSubjectTutorInvitation tid@TermId ssh@SchoolId csh@CourseShorthand tutn@TutorialName: [#{tid}-#{ssh}-#{csh}] Einladung zum Ausbilder für #{tutn}
TutorInviteHeading tutn@TutorialName: Einladung zum Ausbilder/zur Ausbilderin für #{tutn}
@ -49,4 +50,21 @@ TutorialUserGrantQualification: Qualifikation vergeben
TutorialUserRenewQualification: Qualifikation regulär verlängern
TutorialUserRenewedQualification n@Int: Qualifikation für #{tshow n} Kurs-#{pluralDE n "Teilnehmer:in" "Teilnehmer:innen"} regulär verlängert
TutorialUserGrantedQualification n@Int: Qualifikation erfolgreich an #{tshow n} Kurs-#{pluralDE n "Teilnehmer:in" "Teilnehmer:innen"} vergeben
CommTutorial: Kursmitteilung
TutorialUserAssignExam: Zur Prüfung einteilen
TutorialUserExamAssignedFor n@Int m@Int p@Text: #{n}/#{m} zur Prüfung #{p} eingeteilt
CommTutorial: Kursmitteilung
TutorialDrivingPermit: Führerschein
TutorialEyeExam: Sehtest
TutorialNote: Kursnotiz
TutorialDayAttendance day@Text: Anwesenheit #{day}
TutorialDayNote day@Text: Anwesenheitsnotiz #{day}
TutorialParticipantsDayEdits day@Text: Kursteilnehmer-Tagesnotizen aktualisiert für #{day}
PossibleCheckResults: Mögliche Prüfungsergebnisse
CheckEyePermitMissing: Sehtest oder Führerschein fehlen noch
CheckEyePermitIncompatible: Sehtest und Führerschein passen nicht zusammen
GenTutActOccCopyLast: Prüfungstermine von früherem Kurs kopieren
GenTutActOccCopyWeek: Prüfungstermine von früherer Woche kopieren
GenTutActOccEdit: Relevante Prüfungstermine bearbeiten
GenTutActShowExam: Prüfungsergebnisse der Kursteilnehmer anzeigen

View File

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2022 Winnie Ros <winnie.ros@campus.lmu.de>
# SPDX-FileCopyrightText: 2022-25 Winnie Ros <winnie.ros@campus.lmu.de>,Steffen Jost <s.jost@fraport.de>
#
# SPDX-License-Identifier: AGPL-3.0-or-later
@ -12,16 +12,16 @@ TutorialEdited tutn: Successfully edited course #{tutn}
TutorialEditHeading tutn: Edit #{tutn}
TutorEmail: Email
TutorialTutorAlreadyAdded: An user with this email address is already registered as instructor
TutorialNameTip: Needs to be unique within the course type
TutorialNameTip: Needs to be unique within the course category
TutorialTypePlaceholder: Tutorial, Driving lesson, ...
TutorialTypeTip: Only for informational purposes
TutorialRegGroupTip: Course type participants may only register for a maximum of one course per registration group. Courses that do not have a registration group are treated as being in different registration groups
TutorialRegGroupTip: Course category participants may only register for a maximum of one course per registration group. Courses that do not have a registration group are treated as being in different registration groups
TutorialRegGroup: Registration group
TutorialTutorControlled: Instructors may edit course
TutorialTutorControlledTip: Should instructors be allowed to edit arbitrary aspects of this course (name, registration group, room, time, other instructors, ...) at will?
TutorialCapacity: Capacity
TutorialCapacityNonPositive: Capacity may not be negative
TutorialCapacityTip: Limits how many course type participants may register for this course
TutorialCapacityTip: Limits how many course category participants may register for this course
TutorialRoomHiddenTip: Should the room only be displayed to course participants?
RegisterFrom: Enrolment starts
RegisterTo: Enrolment ends
@ -36,6 +36,7 @@ TutorialDelete: Delete
TutorialsHeading: Courses
TutorialNew: New course
TutorialRegisteredSuccess tutn: Successfully registered for the course #{tutn}
TutorialRegisteredFail tutn: Registering for the course #{tutn} failed. Probably already registered?
TutorialDeregisteredSuccess tutn: Successfully de-registered for the course #{tutn}
MailSubjectTutorInvitation tid ssh csh tutn: [#{tid}-#{ssh}-#{csh}] Invitation to be a instructor for #{tutn}
TutorInviteHeading tutn: Invitation to be instructor for #{tutn}
@ -50,4 +51,21 @@ TutorialUserGrantQualification: Grant qualification
TutorialUserRenewQualification: Renew qualification
TutorialUserRenewedQualification n@Int: Successfully renewed qualification #{tshow n} course #{pluralEN n "user" "users"}
TutorialUserGrantedQualification n: Successfully granted qualification #{tshow n} course #{pluralEN n "user" "users"}
TutorialUserAssignExam: Register for examination
TutorialUserExamAssignedFor n@Int m@Int p@Text: #{n}/#{m} enrolled for exam #{p}
CommTutorial: Course message
TutorialDrivingPermit: Driving permit
TutorialEyeExam: Eye exam
TutorialNote: Course note
TutorialDayAttendance day: Attendance #{day}
TutorialDayNote day: Attendance note #{day}
TutorialParticipantsDayEdits day: course participant day notes updated for #{day}
PossibleCheckResults: Possible results
CheckEyePermitMissing: Eye exam or driving permit missing
CheckEyePermitIncompatible: Eye exam and driving permit are incompatible
GenTutActOccCopyLast: Copy exam occurrences from previous course
GenTutActOccCopyWeek: Copy exam occurrences from course on previous week
GenTutActOccEdit: Edit relevant exam occurrences
GenTutActShowExam: Show exam results for course participants

View File

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2023 Steffen Jost <s.jost@fraport.de>
# SPDX-FileCopyrightText: 2023-25 Steffen Jost <s.jost@fraport.de>
#
# SPDX-License-Identifier: AGPL-3.0-or-later
@ -7,7 +7,6 @@ FirmSuperForeign: Firmenfremde Ansprechpartner
FirmSuperIrregular: Irreguläre Ansprechpartner
FirmAssociates: Firmenangehörige
FirmContact: Firmenkontakt
FirmNoContact: Keine allgemeinen Kontaktinformationen bekannt.
FirmEmail: Allgemeine Email
FirmAddress: Postanschrift
FirmDefaultPreferenceInfo: Diese Voreinstellungen gelten nur für neue Firmenangehörige
@ -16,11 +15,18 @@ FirmActionInfo: Betrifft alle Firmenangehörigen unter Ihrer Aufsicht.
FirmActNotify: Mitteilung versenden
FirmActResetSupervision: Ansprechpartner für alle Firmenangehörigen zurücksetzen
FirmActResetSuperKeep: Bisherige Ansprechpartner der Firmenangehörigen zusätzlich beibehalten?
FirmActRemoveSupers: Alle rein firmenbezogenen Ansprechpartnerbeziehungen für diese Personen entfernen?
FirmActResetMutualSupervision: Ansprechpartner beaufsichtigen sich gegenseitig
FirmActAddSupersvisors: Ansprechpartner hinzufügen
FirmActAddSupersEmpty: Es konnten keine Ansprechpartner hinzugefügt werden
FirmActResetSupersKeepAll: Alle behalten
FirmActResetSupersRemoveAps: Nur Standardansprechpartner entfernen
FirmActResetSupersRemoveAll: Alle entfernen
FirmActAddSupervisors: Ansprechpartner hinzufügen
FirmActAddAssociates: Firmenangehörige hinzufügen
FirmActAddSupersEmpty: Es konnten keine neuen Ansprechpartner hinzugefügt werden!
FirmActAddSupersSet n@Int64 postal@(Maybe Bool): #{n} Standardansprechpartner geändert #{maybeBoolMessage postal "" "und auf Briefversand geschaltet" "und Benachrichtigungen per Email gesetzt"}, aber nicht nicht aktiviert.
RemoveSupervisors ndef@Int64 nact@Int64: #{ndef} Standard Ansprechpartner entfernt#{bool ", aber noch nicht deaktiviert" (", " <> tshow nact <> " aktive Ansprechpartnerbeziehungen gelöscht") (nact > 0)}
FirmActAddAssocsEmpty: Es konnten keine neuen Firmenangehörige hinzugefügt werden!
FirmActAddAssocs n@Int64: #{n} Firmenangehörige hinzugefügt.
RemoveSupervisors ndef@Int64: #{ndef} Standardansprechpartner entfernt.
FirmActChangeContactUser: Kontaktinformationen von allen Firmenangehörigen ändern
FirmActChangeContactFirm: Kontaktinformationen der Firma ändern
FirmActChangeContactFirmInfo: Firmenkontaktinformationen werden nur für neue Firmenangehörige verwendet, für die sonst keine Kontaktinformationen vorliegen.
@ -28,17 +34,23 @@ FirmActChangeContactFirmResult: Firmenkontaktinformationen geändert. Betrifft n
FirmUserActNotify: Mitteilung versenden
FirmUserActResetSupervision: Ansprechpartner auf Firmenstandard zurücksetzen
FirmUserActSetSupervisor: Ansprechpartner ändern
FirmUserActChangeContact: Kontaktinformationen für ausgewählte Firmenangehörige ändern
FirmUserActChangeDetails: Firmenassoziation bearbeiten
FirmUserActRemove: Firmenassoziation entfernen
FirmUserActMkSuper: Zum Firmenansprechpartner ernennen
FirmUserActChangeDetailsResult n@Int64 t@Int64: Firmenassoziation von #{n}/#{t} #{pluralDE n "Firmenangehörigen" "Firmenangehörige"} wurden aktualisiert
FirmUserActChangeResult n@Int64 t@Int64: Benachrichtigungseinstellung für #{n}/#{t} #{pluralDE n "Firmenangehörigen" "Firmenangehörige"} wurden geändert
FirmUserActRemoveResult uc@Int64: #{uc} #{pluralDE uc "Firmenassoziation" "Firmenassoziationen"} entfernt.
FirmRemoveSupervision sup@Int64 sub@Int64: #{noneMoreDE sup "" (tshow sup <> " Ansprechpartnerbeziehungen wegen entferntem Ansprechpartner gelöscht. ")} #{noneOneMoreDE sub "Keine Ansprechpartnerbeziehung" "Eine Ansprechpartnerbeziehung" (tshow sup <> " Ansprechpartnerbeziehungen")} wegen entferntem Klienten gelöscht.
FirmNewSupervisor: Neue individuelle Ansprechpartner hinzufügen
FirmSetSupervisor: Existierende Ansprechpartner hinzufügen
FirmSetSupersReport nusr@Int64 nspr@Int64 nrem@Int64: Für #{nusr} Firmenangehörige wurden #{nspr} individuelle Ansprechpartner eingetragen#{bool "." (" und " <> tshow nrem <> " individuelle Ansprechpartnerbeziehungen gelöscht.") (nrem >0)}
FirmUserActMkSuper: Zum Firmenansprechpartner ernennen
FirmUserActChangeContact: Kontaktinformationen für ausgewählte Firmenangehörige ändern
FirmResetSupervision rem@Int64 set@Int64: #{tshow set} Ansprechpartner gesetzt#{bool mempty (", " <> tshow rem <> " zuvor gelöscht") (rem > 0)}
FirmSuperActNotify: Mitteilung versenden
FirmSuperActSwitchSuper: Standard Firmenansprechpartner abändern
FirmSuperActSwitchSuperInfo: Betrifft keine firmenfremden Ansprechpartner und ändert keine aktiven individuellen Ansprechpartnerbeziehungen. Gegebenfalls im Anschluss die Funktion "Ansprechpartner auf Firmenstandard zurücksetzen" nutzen.
FirmSuperActRMSuperDef: Firmenansprechpartner entfernen
FirmSuperActRMSuperActive: Auch aktive Ansprechpartnerbeziehungen innerhalb dieser Firma beenden
FirmSuperActRMSuperActive: Aktive Ansprechpartnerbeziehungen innerhalb dieser Firma beenden?
FirmsNotification: Firmen E-Mail versenden
FirmNotification fsh@CompanyShorthand: E-Mail an #{fsh} senden
FirmsNotificationTitle: Firmen benachrichtigen
@ -47,14 +59,39 @@ FilterSupervisor: Hat aktiven Ansprechpartner
FilterSupervisorCompany fsh@CompanyShorthand: Hat aktiven Ansprechpartner, #{fsh} der angehört
FilterSupervisorForeign fsh@CompanyShorthand: Hat aktiven Ansprechpartner, der selbst nicht #{fsh} angehört
FilterForeignSupervisor: Hat firmenfremde Ansprechpartner
FilterIsForeignSupervisee: Ist Ansprechpartner für Firmenfremde
FilterFirmExtern: Externe Firma
FilterFirmExternTooltip: Hat die Firma eine Postanschrift im AVS?
FilterFirmPrimary: Ist primäre Firma in FRADrive
FilterHasQualification: Hat Firmenangehörige mit aktuell gültiger Qualifikation
FirmSupervisorOf fsh@CompanyShorthand: Ansprechpartner #{fsh} angehörig
FirmSupervisorIndependent: Ansprechpartner ohne jegliche Firmenzugehörigkeit
FirmEmployeeOf fsh@CompanyShorthand: Firmenangehörige #{fsh}
NoCompanySelected: Bitte wählen Sie mindestens eine Firma aus.
TableIsDefaultSupervisor: Standardansprechpartner
TableSuperior: Vorgesetzter
TableIsDefaultReroute: Standardumleitung
FormFieldPostal: Benachrichtigungseinstellung
FormFieldPostalTip: Gilt für alle Benachrichtigungen an diese Person, nicht nur für Umleitungen an diesen Ansprechpartner
FirmUserChanges n@Int64: Benachrichtigungseinstellung für #{n} Firmenangehörige wurden geändert
FirmSupervisionKeyData: Kennzahlen Ansprechpartner
FormFieldPinPass: Sensible PDF-E-Mail-Anhänge mit Passwort schützen?
FormFieldPinPassRemove: Passwortschutz für PDF-E-Mail-Anhänge entfernen?
FirmSupervisionKeyData: Kennzahlen Ansprechpartner
CompanyUserPriority: Firmenpriorität
CompanyUserPriorityTip: Firmenpriorität ist lediglich relativ zu anderen Firmenassoziation der Person
CompanyUserUseCompanyAddress: Verwendet Firmenkontaktaddresse
CompanyUserUseCompanyAddressTip: sofern im Benutzer keine Postanschrift hinterlegt ist
CompanyUserUseCompanyPostalError: Postalische Adresse muss leer bleiben, damit die Firmenanschrift genutzt wird!
CompanySupervisorCompanyMissing fsh@CompanyShorthand: Empfänger ist nicht mit Firma #{fsh} aus Ansprechpartnerbeziehung assoziiert
CompanySuperviseeCompanyMissing fsh@CompanyShorthand: Klient ist nicht mit Firma #{fsh} aus Ansprechpartnerbeziehung assoziiert
FirmSupervisionRInfo: In folgenden Ansprechpartnerbeziehungen gehören entweder der Ansprechpartner oder der Klient nicht mehr der Firma an, welche als Begründung für die Beziehung eingetragen ist.
SupervisionViolationChoice: Firmenassoziation fehlt für
SupervisionViolationEither: Egal
SupervisionViolationSupervisor: Ansprechpartner
SupervisionViolationClient: Klient
SupervisionViolationBoth: Beide
SupervisionsRemoved n@Int64 m@Int64: #{n}/#{m} #{pluralDE n "Ansprechpartnerbeziehung" "Ansprechpartnerbeziehungen"} entfernt.
SupervisionsEdited n@Int64 m@Int64: #{n}/#{m} #{pluralDE n "Ansprechpartnerbeziehung" "Ansprechpartnerbeziehungen"} geändert.
ASChangeCompany: Begründungen für Ansprechpartnerbeziehung abändern
ASRemoveAssociation: Ansprechpartnerbeziehung löschen
FirmNameNotFound: Keine Firma mit diesen Namen/Kürzel/AVS-Nr gefunden.
FirmNameAmbiguous: Firmenname/-kürzel oder AVS-Nr ist nicht eindeutig.

View File

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2023 Steffen Jost <s.jost@fraport.de>
# SPDX-FileCopyrightText: 2023-25 Steffen Jost <s.jost@fraport.de>
#
# SPDX-License-Identifier: AGPL-3.0-or-later
@ -7,7 +7,6 @@ FirmSuperForeign: External supervisor
FirmSuperIrregular: Irregular supervisor
FirmAssociates: Company associated users
FirmContact: Company Contact
FirmNoContact: No general contact information known.
FirmEmail: General company email
FirmAddress: Postal address
FirmDefaultPreferenceInfo: Default setting for new company associates only
@ -16,11 +15,18 @@ FirmActionInfo: Affects alle company associates under your supervision.
FirmActNotify: Send message
FirmActResetSupervision: Reset supervisors for all company associates
FirmActResetSuperKeep: Additionally keep existing supervisors of company associates?
FirmActRemoveSupers: Terminate all company related supervisionships?
FirmActResetMutualSupervision: Supervisors supervise each other
FirmActAddSupersvisors: Add supervisors
FirmActAddSupersEmpty: No supervisors added
FirmActResetSupersKeepAll: Keep all
FirmActResetSupersRemoveAps: Remove default supervisors only
FirmActResetSupersRemoveAll: Remove all
FirmActAddSupervisors: Add supervisors
FirmActAddAssociates: Associate users with company
FirmActAddSupersEmpty: No new supervisors added!
FirmActAddSupersSet n postal: #{n} default company supervisors changed #{maybeBoolMessage postal "" "and switched to postal notifications" "and switched to email notifications"}, but not yet activated.
RemoveSupervisors ndef nact: #{ndef} default supervisors removed#{bool ", but not yet deactivated" (" and " <> tshow nact <> " active supervisions terminated") (nact > 0)}
FirmActAddAssocsEmpty: No new company associated users added!
FirmActAddAssocs n: #{pluralENsN n "company associated user"} added.
RemoveSupervisors ndef: #{ndef} default supervisors removed.
FirmActChangeContactUser: Change contact data for all company associates
FirmActChangeContactFirm: Change company contact data
FirmActChangeContactFirmInfo: The company contact data is only used for new company associates that would habe no contact information of their own otherwise.
@ -28,17 +34,23 @@ FirmActChangeContactFirmResult: Company contact data changed, affecting future c
FirmUserActNotify: Send message
FirmUserActResetSupervision: Reset supervisors to company default
FirmUserActSetSupervisor: Change supervision
FirmUserActChangeContact: Change contact data for selected company associates
FirmUserActChangeDetails: Edit company association
FirmUserActRemove: Delete company association
FirmUserActMkSuper: Mark as company supervisor
FirmUserActChangeDetailsResult n t: #{n}/#{t} #{pluralENs n "company association"} updated
FirmUserActChangeResult n t: Notification settings changed for #{n}/#{t} company #{pluralENs n "associate"}
FirmUserActRemoveResult uc: #{pluralENsN uc "Company association"} deleted.
FirmRemoveSupervision sup sub: #{noneMoreEN sup "" ((pluralENsN sup "supervision") <> " removed due to eliminated supervisors.")} #{noneMoreEN sub "No supervision" (pluralENsN sub "supervision")} removed due to eliminated supervisees.
FirmNewSupervisor: Appoint new individual supervisors
FirmSetSupervisor: Add existing supervisors
FirmSetSupersReport nusr@Int64 nspr@Int64 nrem@Int64: #{nspr} individal supervisors set for #{nusr} company associates#{bool "." (" and " <> tshow nrem <> " other individual supervisions terminated.") (nrem >0)}
FirmSetSupersReport nusr nspr nrem: #{nspr} individual supervisors set for #{nusr} company associates#{bool "." (" and " <> tshow nrem <> " other individual supervisions terminated.") (nrem >0)}
FirmResetSupervision rem set: #{tshow set} supervisors set#{bool mempty (", " <> tshow rem <> " deleted before") (rem > 0)}
FirmUserActChangeContact: Change contact data for selected company associates
FirmUserActMkSuper: Mark as company supervisor
FirmSuperActNotify: Send message
FirmSuperActSwitchSuper: Change default company supervisor
FirmSuperActSwitchSuperInfo: Does not affect company-external supervisors and does not change any active individal supervisions. Additionally use reset action, if desired.
FirmSuperActSwitchSuperInfo: Does not affect company-external supervisors and does not change any active individual supervisions. Additionally use reset action, if desired.
FirmSuperActRMSuperDef: Remove default supervisor
FirmSuperActRMSuperActive: Also remove active supervisions within this company
FirmSuperActRMSuperActive: Terminate active supervisions within this company?
FirmsNotification: Send company notification e-mail
FirmNotification fsh: Send e-mail to #{fsh}
FirmsNotificationTitle: Company notification
@ -47,14 +59,39 @@ FilterSupervisor: Has active supervisor
FilterSupervisorCompany fsh: Has active company supervisor belonging to #{fsh}
FilterSupervisorForeign fsh: Has active supervisor not belonging to #{fsh}
FilterForeignSupervisor: Has company-external supervisors
FilterIsForeignSupervisee: Supervisor for company external users
FilterFirmExtern: External company
FilterFirmExternTooltip: i.e. is a postal address registered within AVS?
FilterFirmPrimary: Is primary company in FRADrive
FilterHasQualification: Has company associates with currently valid qualification
FirmSupervisorOf fsh@CompanyShorthand: Supervisors belonging to #{fsh}
FirmSupervisorIndependent: Independent supervisors
FirmEmployeeOf fsh@CompanyShorthand: #{fsh} associated users
NoCompanySelected: Select at least one company, please.
TableIsDefaultSupervisor: Default supervisor
TableSuperior: Superior
TableIsDefaultReroute: Default reroute
FormFieldPostal: Notification type
FormFieldPostalTip: Affects all notifications to this person, not just reroutes to this supervisor
FirmUserChanges n: Notification settings changed for #{n} company associates
FirmSupervisionKeyData: Supervision key data
FormFieldPinPass: Protect sensitive PDF e-mail attachments by password?
FormFieldPinPassRemove: Remove password protection for PDF e-mail attachments?
FirmSupervisionKeyData: Supervision key data
CompanyUserPriority: Company priority
CompanyUserPriorityTip: Company priority is relative to other company associations for a user
CompanyUserUseCompanyAddress: Use company postal address
CompanyUserUseCompanyAddressTip: if and only if the postal address of the user is empty
CompanyUserUseCompanyPostalError: Individual postal address must left empty for the company address to be used!
CompanySupervisorCompanyMissing fsh: Receiver is not associated with #{fsh} given as reroute reason
CompanySuperviseeCompanyMissing fsh: Supervisee is not associated with #{fsh} detailed as supervisionship reason
FirmSupervisionRInfo: Shown are supervisionships where either supervisor or supervisee no longer belong to the company associated with the supervisionship.
SupervisionViolationChoice: Company association missing for
SupervisionViolationEither: anyone
SupervisionViolationSupervisor: Supervisor
SupervisionViolationClient: Supervisee
SupervisionViolationBoth: both
SupervisionsRemoved n m: #{n}/#{m} #{pluralENs n "Supervisionship"} removed.
SupervisionsEdited n m: #{n}/#{m} #{pluralENs n "Supervisionship"} edited.
ASChangeCompany: Change supervisionship annotations
ASRemoveAssociation: Delete supervisionship
FirmNameNotFound: No company found with this name/shorthand or AVS number.
FirmNameAmbiguous: Company name/shorthand or AVS number is amiguous.

View File

@ -6,7 +6,7 @@ HeadingLegal: Legal
InfoSupervisorTitle: Information for supervisors
InfoLecturerTitle: Information for course administrators
InfoLecturerCourses: Courses
InfoLecturerExercises: Course type exercises
InfoLecturerExercises: Course category exercises
InfoLecturerTutorials: Courses
InfoLecturerExams: Exams
LecturerInfoTooltipNew: New feature
@ -20,8 +20,8 @@ KnownBugs: Known bugs
ImplementationDetails: Implementation
Clone: Cloning
Administrator: Administrator
CommCourse: Course type message
CommCourse: Course category message
Corrector: Corrector
DefinitionCourseEvents: Course type occurrences
DefinitionCourseNews: Course type news
DefinitionCourseEvents: Course category occurrences
DefinitionCourseNews: Course category news
Invitations: Invitations

View File

@ -17,7 +17,8 @@ PrintJobReprint n@Int m@Int: #{n}/#{m} #{pluralDE n "Druckauftrag" "Druckaufräg
PrintJobAcknowledgeFailed: Keine Druckaufträge bestätigt aufgrund zwischenzeitlicher Änderungen. Bitte die Seite im Browser aktualisieren!
PrintJobAcknowledgeQuestion n@Int d@Text: #{n} #{pluralDE n "Druckauftrag" "Druckaufräge"} vom #{d} als gedruckt und versendet bestätigen?
PrintJobAcknowledgements: Versanddatum von Briefen an
PrintRecipient: Empfänger
PrintRecipient: Empfänger:innen
PrintAffected: Betroffener
PrintSender !ident-ok: Sender
PrintCourse: Kursarten
PrintQualification: Qualifikation
@ -25,4 +26,7 @@ PrintPDF !ident-ok: PDF
PrintManualRenewal: Vorfeldführerschein Renewal-Brief testweise versenden
PrintLmsUser: ELearning Id
PrintJobs: Druckaufräge
PrintLetterType: Brieftypkürzel
PrintLetterType: Brieftypkürzel
MCActDummy: Platzhalter
CCActDummy: Platzhalter

View File

@ -18,11 +18,15 @@ PrintJobAcknowledgeFailed: No print-jobs acknowledged, due to intermediate chang
PrintJobAcknowledgeQuestion n d: Mark #{n} #{pluralENs n "print-job"} issued on #{d} as printed and mailed already?
PrintJobAcknowledgements: Sent-dates for Letter to
PrintRecipient: Recipient
PrintAffected: Affetcted
PrintSender: Sender
PrintCourse: Course type
PrintCourse: Course category
PrintQualification: Qualification
PrintPDF: PDF
PrintManualRenewal: Manual sending of an apron driver's licence renewal letter
PrintLmsUser: Elearning id
PrintJobs: Print jobs
PrintLetterType: Letter type shorthand
PrintLetterType: Letter type shorthand
MCActDummy: Placeholder
CCActDummy: Placeholder

View File

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2022 Steffen Jost <jost@cip.ifi.lmu.de>,Steffen Jost <jost@tcs.ifi.lmu.de>
# SPDX-FileCopyrightText: 2022-25 Steffen Jost <jost@cip.ifi.lmu.de>,Steffen Jost <jost@tcs.ifi.lmu.de>
#
# SPDX-License-Identifier: AGPL-3.0-or-later
@ -7,25 +7,36 @@ QualificationName: Qualifikation
QualificationDescription: Beschreibung
QualificationValidIndicator: Gültigkeit
QualificationValidDuration: Gültigkeitsdauer
QualificationAuditDuration: Aufbewahrung Audit Log
QualificationAuditDurationTooltip n@Int: Optionaler Zeitraum zur Löschung von ELearning Daten. Hinweis: Der ELearning Server kann seine anonymisierten Daten schon früher löschen, aber spätestens #{n} Tage nach Abschluss.
QualificationAuditDuration: Aufbewahrungszeitraum ELearning Log
QualificationAuditDurationTooltip: Anzahl Tage zur Löschung von ELearning Daten. Hinweis: Der ELearning Server kann seine anonymisierten Daten schon früher löschen.
QualificationAuditDurationReuseInfo: Aufbewahrungszeitraum ELearning Log wird ignoriert, da das ELearning einer anderen Qualifikation mitbenutzt wird.
QualificationRefreshWithin: Erneurerungszeitraum
QualificationRefreshWithinTooltip: Optionaler Zeitraum vor Ablauf für automatischen Start des ELearnings und Versand einer Benachrichtigung per Brief oder Email.
QualificationRefreshReminder: 2. Erinnerung
QualificationRefreshReminderTooltip: Optionaler Zeitraum vor Ablauf zur Versendung einer zweiten Erinnerung per Brief oder Email mit identischen Zugangsdaten, sofern in diesem Zeitraum vor Ablauf noch keine Ablaufbenachrichtigung versendet wurde.
QualificationRefreshWithinTooltip: Optionaler Zeitraum vor Ablauf für eine Benachrichtigung per Email. Bei aktiviertem automatischem ELearning wird dieses gestartet und die Benachrichtigung erfolgt per Brief oder Email.
QualificationRefreshReminder: Zweite Erinnerung
QualificationRefreshReminderTooltip: Optionaler Zeitraum vor Ablauf zur Versendung einer zweiten Erinnerung per Brief oder Email mit identischen ELearning Zugangsdaten, sofern die Qualifikation noch gültig und das ELearning noch offen ist.
QualificationElearningStart: Wird das ELearning automatisch gestartet?
QualificationElearningRenew: Verlängert ein erfolgreiches ELearning die Qualifikation automatisch um die reguläre Gültigkeitsdauer?
QualificationElearningLimit: Limit Anzahl ELearning Versuche
QualificationElearningLimitExplain: Ist die Anzahl der ELearning Versuche limitiert?
QualificationElearningLimitMax n@Int: Maximal #{n} Versuche
QualificationElearningNoLimit: Nicht limitiert
QualificationExpiryNotification: Ungültigkeitsbenachrichtigung?
QualificationExpiryNotificationTooltip: Nutzer werden benachrichtigt, wenn die Qualifikation ungültig wird, sofern der jeweilige Nutzer in seinen Benutzereinstellungen diese Art Benachrichtigung aktiviert hat.
QualificationExpiryNotificationTooltip: Nutzer werden benachrichtigt, wenn die Qualifikation ungültig wird, sofern der jeweilige Nutzer in seinen Benutzereinstellungen diese Art Benachrichtigung nicht deaktiviert hat.
QualificationAvsLicence: AVS Qualifikation
QualificationSapId: SAP Qualifikations Id
TableQualificationCountActive: Aktive
TableQualificationCountActiveTooltip: Anzahl Personen mit momentan gültiger Qualifikation
TableQualificationCountTotal: Gesamt
TableQualificationLmsReuses: LMS nutzt
TableQualificationLmsReusesTooltip: Diese Qualifikation hat kein eigenes ELearning, sondern wird über das ELearning der angegebenen Qualifikation abgewickelt.
TableQualificationIsAvsLicence: AVS
TableQualificationIsAvsLicenceTooltip: Unter welchem Namen wird diese Qualifikation mit dem Ausweisverwaltungssystem (AVS) synchronisiert? Betrifft nur Benutzer mit AVS PersonenID.
TableQualificationSapExport: SAP
TableQualificationSapExportTooltip: Wird die Qualifikation an das SAP übermittelt? Betrifft nur Benutzer mit Fraport Personalnummer.
LmsQualificationValidUntil: Gültig bis
TableQualificationLastRefresh: Zuletzt erneuert
TableQualificationLastNotified: Letzte Benachrichtigung
TableQualificationLastNotified: Letzte Benachrichtigung über erfolgte Gültigkeitsänderung
TableQualificationLastNotifiedTooltip: Hier werden ausschließlich Benachrichtigungen berücksichtigt, die über einen bereits erfolgten Ablauf/Entzug/Wiedererteilung informieren. Dies ignoriert insbesondere reguläre Verlängerung, z.B. durch E-Learning.
TableQualificationFirstHeld: Erstmalig
TableQualificationBlockedDue: Entzug
TableQualificationBlockedTooltip: Wann wurde die Qualifikation vorübergehend außer Kraft gesetzt und warum wurde dies veranlasst?
@ -46,11 +57,13 @@ QualificationExpired: Ungültig seit
LmsUser: Inhaber
LmsURL: Link ELearning
TableLmsEmail: EMail
TableLmsIdent: E-Learning Benutzer
TableLmsIdent: ELearning Benutzer
TableLmsElearning: ELearning
TableLmsElearningRenews: Automatische Verlängerung
TableLmsElearningLimit: Maximale Versuche
TableLmsPin: ELearning Passwort
TableLmsResetPin: E-Learning Passwort zurücksetzen?
TableLmsDatePin: E-Learning Passwort erstellt
TableLmsResetPin: ELearning Passwort zurücksetzen?
TableLmsDatePin: ELearning Passwort erstellt
TableLmsDate: Datum
TableLmsDelete: Löschen?
TableLmsStaff: Interner Mitarbeiter?
@ -60,7 +73,7 @@ TableLmsNotified: Versand Benachrichtigung
TableLmsNotifiedTooltip: Benachrichtigungen werden erst versendet wenn das LMS bestätigt die Eröffnung des ELearning für den Benutzer bestätigt hat, was ein paar Stunden dauern kann!
TableLmsEnded: Beendet
TableLmsStatus: Status ELearning
TableLmsStatusTooltip mbMonth@(Maybe Int): Zeigt #{maybeToMessage "bis zu " (fmap (flip pluralDEeN "Monat") mbMonth) " nach Abschluss"} den letzten Zustand eines ELearnings an:
TableLmsStatusTooltip n@Int: Zeigt bis zu #{pluralDEeN n "Tag"} nach Abschluss den letzten Zustand eines ELearnings an:
TableLmsStatusDay: Datum letzte Statusänderung ELearning
TableLmsSuccess: Bestanden
TableLmsLock: Gesperrt
@ -70,6 +83,7 @@ LmsStatusExpired: Durchgefallen nach Fristablauf
LmsStatusSuccess: E#{nonBreakableDash}Learning bestanden
LmsStatusPlanned: E#{nonBreakableDash}Learning wird gerade noch eröffnet (nur für Admin sichtbar)
LmsStatusDelay: Hinweis: Statusänderung können in seltenen Fällen mehrere Stunden bis zur Anzeige benötigen.
FilterLmsLongValid: Längerfristig gültig
FilterLmsValid: Aktuell gültig
FilterLmsRenewal: Erneuerung anstehend
FilterLmsNotified: Benachrichtigt
@ -88,7 +102,8 @@ LmsReportInsert: Neues LMS Ereignis
LmsReportUpdate: LMS Ereignis Aktualisierung
LmsReportCsvExceptionDuplicatedKey: CSV-Import LmsReport fand uneindeutigen Schlüssel
LmsDirectUpload: Direkter Upload für automatisierte Systeme
LmsErrorNoRefreshElearning: Fehler: ELearning wird nicht automatisch gestartet, da die Zeitspanne für den Erneurerungszeitraum nicht festgelegt wurde.
LmsErrorNoRefreshElearning: Fehler: ELearning wird nicht automatisch gestartet, da die Zeitspanne für den Erneuerungszeitraum nicht festgelegt wurde!
LmsErrorNoRenewElearning: Fehler: Erfolgreiches ELearning verlängert die Qualifikation nicht automatisch, da die Gültigkeitsdauer nicht festgelegt wurde!
MailSubjectQualificationRenewal qname@Text: Qualifikation #{qname} muss demnächst erneuert werden
MailSubjectQualificationExpiry qname@Text: Qualifikation #{qname} läuft demnächst ab
MailSubjectQualificationExpired qname@Text: Qualifikation #{qname} ist ab sofort ungültig
@ -105,24 +120,30 @@ QualificationActBlock: Entziehen
QualificationActUnblock: Entzug aufheben
QualificationActRenew: Qualifikation regulär verlängern
QualificationActGrant: Qualifikation vergeben
QualificationActGrantWarning: Diese Funktion ist nur für seltene Ausnahmefälle vorgesehen! Ein Entzug wird ggf. aufgehoben.
QualificationActGrantWarning: Diese Funktion ist nur für seltene Ausnahmefälle vorgesehen! Ein Entzug wird ggf. aufgehoben; ELearning wird ggf. beendet.
QualificationActStartELearning: ELearning für gültige Inhaber (neu) starten
QualificationActStartELearningStatus l@QualificationShorthand n@Int m@Int: ELearning #{l} für #{n}/#{m} Teilnehmer (neu) gestartet. Hinweis: Es kann länger dauern, bis das LMS tatsächlich startet.
QualificationStatusBlock l@QualificationShorthand n@Int m@Int: #{n}/#{m} #{l} entzogen
QualificationStatusUnblock l@QualificationShorthand n@Int m@Int: #{n}/#{m} #{l} reaktiviert
LmsInactive: Aktuell kein ELearning aktiv
LmsRenewalInstructions: Weitere Anweisungen zur Verlängerung finden Sie im angehängten PDF. Um Missbrauch zu verhindern wurde das PDF mit dem im FRADrive hinterlegten PDF-Passwort des Prüflings verschlüsselt. Falls kein PDF-Passwort manuell hinterlegt wurde, ist das PDF-Passwort die Flughafen Ausweisnummer, inklusive Punkt und der Ziffer danach.
LmsNoRenewal: Leider kann diese Qualifikation nicht alleine durch ELearning verlängert werden.
LmsNoRenewal: Leider kann diese Qualifikation nicht alleine durch ELearning verlängert werden. Bitte setzen Sie sich mit uns in Verbindung, wenn Sie die Qualifikation verlängern möchten und noch nicht wissen, wie Sie das tun können. Ignorieren Sie diese automatisch generierte Erinnerung, falls Sie sich bereits um die Verlängerung gekümmert haben
LmsRenewalReminder: Erinnerung
LmsActNotify: Benachrichtigung ELearning erneut per Post oder E-Mail versenden
LmsActRenewPin: Neues zufällige ELearning Passwort zuweisen
LmsActRenewNotify: Neue zufällige ELearning Passwort zuweisen und Benachrichtigung per Post oder E-Mail versenden
LmsActRenewNotify: Neues zufälliges ELearning Passwort zuweisen und Benachrichtigung per Post oder E-Mail versenden
LmsActReset: ELearning Fehlversuche zurücksetzen und entsperren
LmsActResetInfo: ELearning Login, Passwort und Fortschritt bleiben unverändert, eine neue Benachrichtigung ist nicht notwendig. Nur möglich für bereits gesperrte Lerner. Es kann bis zu 2 Stunden dauern, bis das LMS die Anfrage umgesetzt hat.
LmsActResetFeedback n@Int m@Int: Für #{n}/#{m} ELearning Nutzer wurden alle Fehlversuche zurückgesetzt.
LmsActRestart: ELearning komplett neu starten
LmsActRestartWarning: Das vorhandene ELearning wird komplett gelöscht! Für Inhaber einer gültigen Fahrlizenz werden später Benutzer und Passwort neu vergeben und es sollte eine neue Benachrichtigung versendet werden. Hinweis: Es kann mehrere Stunden dauern, bis das LMS diese Anfrage umgesetzt hat.
LmsActRestartWarning: Das vorhandene ELearning wird komplett gelöscht! Für Inhaber einer gültigen Lizenz werden später Benutzer und Passwort neu vergeben und es sollte eine neue Benachrichtigung versendet werden. Hinweis: Es kann mehrere Stunden dauern, bis das LMS diese Anfrage umgesetzt hat.
LmsActRestartFeedback n@Int m@Int: #{n}/#{m} ELearning Nutzer wurden komplett neu gestartet mit neuem Login und Passwort.
LmsActRestartExtend: Gültig bis ggf. erhöhen für die nächsten # Tage
LmsActRestartUnblock: Entzug ggf. aufheben
LmsActTerminate: ELearning abbrechen
LmsActTerminateInfo: Ein späterer automatischer Neustart des ELearning wird dadurch nicht verhindert, wenn eine gültige Qualifikation bald abläuft und ELearning für diese Qualifikation generell automatisch startet.
LmsActTerminateFeedback n@Int m@Int: #{n}/#{m} ELearning Nutzer wurden zur Löschung freigegeben.
LmsActTerminated n@Int: ELearning für #{n} Nutzer wurde beendet.
LmsActTerminateWarning: ACHTUNG: Ein Ergebnis würde ohne Warnung verworfen, sollte ein Nutzer sein ELearning absolvieren, bevor die Löschung beim Elearning Server effektiv wurde.
LmsStateOpen: ELearning offen
LmsStatusLocked: ELearning gesperrt, wird ggf. bald geöffnet
LmsStatusUnlocked: ELearning offen, wird ggf. bald gesperrt
@ -134,3 +155,18 @@ LmsActionFailed n@Int: Aktion nicht durchgeführt für #{n} #{pluralDE n "Person
LmsStarted: ELearning eröffnet
BtnLmsEnqueue: Nutzer mit ablaufenden Qualifikationen zum ELearning anmelden und benachrichtigen
BtnLmsDequeue: Nutzer mit beendetem ELearning aufräumen und ggf. benachrichtigen
QualificationEditNote: Hinweis: Die Änderungen treten sofort in Kraft. Bitte vergewissern Sie sich vorher, dass alles korrekt eingestellt wurde!
QualificationCreated qsh@Text: Qualifikation #{qsh} wurde angelegt.
QualificationEdit qsh@Text: Qualifikation #{qsh} wurde geändert.
QualFormErrorDuplShort qsh@Text: Es gibt bereits eine Qualifikation mit Kürzel #{qsh}!
QualFormErrorDuplName qname@Text: Es gibt bereits eine Qualifikation mit Namen #{qname}!
QualFormErrorSshMismatch: Qualifikationänderungsformular enthält unglültige Bereichsangabe. Bitte versuchen Sie erneut, nachdem Sie Seite neu geladen haben.
LmsOrphans: Verwaiste Logins
LmsOrphanNr n@Int: #{n} verwaiste ELearning Logins für diese Qualifikation erkannt.
LmsOrphanSeenFirst: Zuerst erkannt
LmsOrphanSeenLast: Zuletzt erhalten
LmsOrphanDeletedLast: Zuletzt Löschung beantragt
LmsOrphanReason: Bemerkung
LmsOrphanPreviewFltr: Löschungen bei nächstem Abruf anfordern?

View File

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2022 Steffen Jost <jost@cip.ifi.lmu.de>,Steffen Jost <jost@tcs.ifi.lmu.de>
# SPDX-FileCopyrightText: 2022-25 Steffen Jost <jost@cip.ifi.lmu.de>,Steffen Jost <jost@tcs.ifi.lmu.de>
#
# SPDX-License-Identifier: AGPL-3.0-or-later
@ -8,24 +8,35 @@ QualificationDescription: Description
QualificationValidIndicator: Validity
QualificationValidDuration: Validity period
QualificationAuditDuration: Audit log retention period
QualificationAuditDurationTooltip n@Int: Optional period for deletion of elearning data. Note that the elearning server may delete its anonymised data earlier, at most #{n} days after closing.
QualificationAuditDurationTooltip: Days for deletion of elearning data. Note that the elearning server may delete its anonymised data earlier.
QualificationAuditDurationReuseInfo: Elearning audit log retention period ignore, since the elearning from another qualification is reused.
QualificationRefreshWithin: Refresh within
QualificationRefreshWithinTooltip: Optional period before expiry to start elearning and send a notification by post or email.
QualificationRefreshReminder: 2. Reminder
QualificationRefreshReminderTooltip: Optional period before expiry to send a second notification by post or email once more, provided that no renewal notification was sent in this period before expiry.
QualificationRefreshWithinTooltip: Optional period before expiry to send a notification by email. If elearning is set to start automatically, it will be started and elearning credentials are send with this notification by post or email.
QualificationRefreshReminder: Second reminder
QualificationRefreshReminderTooltip: Optional period before expiry to send a second notification by post or email once more, including the existing credentials, provided that the elearning is still undecided and the qualification has not yet expired.
QualificationElearningStart: Is elearning automatically started?
QualificationExpiryNotification: Invalidity notification?
QualificationExpiryNotificationTooltip: Qualification holder are notfied upon invalidity, provided they have activated such notification in their user settings.
QualificationElearningRenew: Does successful elearning automatically extend a qualification by the default validity period?
QualificationElearningLimit: Limit of elearning attempts
QualificationElearningLimitExplain: Is the number of elearning attempts limited?
QualificationElearningLimitMax n: #{n} attempts maximum
QualificationElearningNoLimit: No limit
QualificationExpiryNotification: Notification upon invalidation?
QualificationExpiryNotificationTooltip: Qualification holder are notfied upon invalidation, provided they have not deactivated such notification in their user settings.
QualificationAvsLicence: AVS Qualification
QualificationSapId: SAP Qualification Id
TableQualificationCountActive: Active
TableQualificationCountActiveTooltip: Number of currently valid qualification holders
TableQualificationCountTotal: Total
TableQualificationLmsReuses: Reuse LMS
TableQualificationLmsReusesTooltip: This qualification reuses the elearning of the given qualification, instead of having a separate elearning of its own.
TableQualificationIsAvsLicence: AVS driving license
TableQualificationIsAvsLicenceTooltip: Under which name is this qualification synchronized with AVS, if any? Only applies to qualification holders having an AVS PersonID.
TableQualificationSapExport: Sent to SAP
TableQualificationSapExportTooltip: Is this qualification transmitted to SAP? Only applies to qualification holder having a Fraport AG personnel number.
LmsQualificationValidUntil: Valid until
TableQualificationLastRefresh: Last renewed
TableQualificationLastNotified: Last notified
TableQualificationLastNotified: Last notified about validity change
TableQualificationLastNotifiedTooltip: The date of the last notification about any already effective change in validity due to revocation or reissue. This does not entail regular validity extensions, e.g. due to e-learning.
TableQualificationFirstHeld: First held
TableQualificationBlockedDue: Revocations
TableQualificationBlockedTooltip: Why and when was this qualification temporarily suspended?
@ -49,6 +60,8 @@ TableLmsEmail: Email
TableLmsIdent: Elearning user
TableLmsPin: Elearning password
TableLmsElearning: Elearning
TableLmsElearningRenews: Automatic renewal
TableLmsElearningLimit: Max attempts
TableLmsResetPin: Reset Elearning password?
TableLmsDatePin: Elearning password created
TableLmsDate: Date
@ -57,10 +70,10 @@ TableLmsStaff: Staff?
TableLmsStarted: Started
TableLmsReceived: Last update
TableLmsNotified: Notification sent
TableLmsNotifiedTooltip: Notfications are not sent before the LMS acknowledges the opening of the elearning course type for the user, which may take several hours!
TableLmsNotifiedTooltip: Notfications are not sent before the LMS acknowledges the opening of the elearning course category for the user, which may take several hours!
TableLmsEnded: Ended
TableLmsStatus: Status elearning
TableLmsStatusTooltip mbMonth: Shows #{maybeToMessage "for up to " (fmap (flip pluralENsN "month") mbMonth) " after closure"} the last e#{nonBreakableDash}learning status change:
TableLmsStatusTooltip n: Shows for up to #{pluralENsN n "day"} after closure the last e#{nonBreakableDash}learning status change:
TableLmsStatusDay: Date of last elearning status change
TableLmsSuccess: Completed
TableLmsLock: Locked
@ -70,6 +83,7 @@ LmsStatusExpired: Failed due to expiry
LmsStatusSuccess: Passed
LmsStatusPlanned: E#{nonBreakableDash}learning is about to be opened soon (visible to Admins only)
LmsStatusDelay: Note that status changes may occassionaly require more than a hour to be displayed here.
FilterLmsLongValid: Long-term valid
FilterLmsValid: Currently valid
FilterLmsRenewal: Renewal due
FilterLmsNotified: Notified
@ -88,7 +102,8 @@ LmsReportInsert: New LMS event
LmsReportUpdate: Update of LMS event
LmsReportCsvExceptionDuplicatedKey: CSV Import LmsReport with ambiguous key
LmsDirectUpload: Direct upload for automated systems
LmsErrorNoRefreshElearning: Error: Elearning will not be started automatically due to refresh-within time period not being set.
LmsErrorNoRefreshElearning: Error: Elearning will not be started automatically due to refresh-within time period not being set!
LmsErrorNoRenewElearning: Error: Elearning will not automatically extend validity due to validity duration not being set!
MailSubjectQualificationRenewal qname: Qualification #{qname} must be renewed shortly
MailSubjectQualificationExpiry qname: Qualification #{qname} expires soon
MailSubjectQualificationExpired qname: Qualification #{qname} is no longer valid
@ -105,15 +120,16 @@ QualificationActBlock: Revoke
QualificationActUnblock: Clear revocation
QualificationActRenew: Renew qualification
QualificationActGrant: Grant qualification
QualificationActGrantWarning: Use with caution in rare exceptional cases only! Any revocation will be undone.
QualificationActGrantWarning: Use with caution in rare exceptional cases only! Any revocation will be undone; any elearning terminated
QualificationActStartELearning: Manually (re)start elearning for valid qualification holders
QualificationActStartELearningStatus l n m: Elearning #{l} (re)started for #{n}/#{m} users. Note: It may take a while, until the elearning is activated.
QualificationStatusBlock l n m: #{n}/#{m} #{l} revoked
QualificationStatusUnblock l n m: #{n}/#{m} #{l} reactivated
LmsInactive: Currently no active elearning
LmsRenewalInstructions: Instruction on how to accomplish the renewal are enclosed in the attached PDF. In order to avoid misuse, the PDF is encrypted with the FRADrive PDF-password of the examinee. If no PDF-password had been chosen yet, then the password is the Fraport id card number of the examinee, including the punctuation mark and the digit thereafter.
LmsNoRenewal: Unfortunately, this particular qualification cannot be renewed through elearning only.
LmsNoRenewal: Unfortunately, this particular qualification cannot be renewed through elearning only. Please contact us, if you do not yet know how to renew this qualification. Ignore this automatically generated reminder email, if you have made arrangements for the renewal of this qualification already.
LmsRenewalReminder: Reminder
LmsActNotify: Resend elearning notification by post or email
LmsActRenewPin: Randomly replace elearning password
LmsActRenewNotify: Randomly replace elearning password and re-send notification by post or email
LmsActReset: Reset and unlock elearning
LmsActResetInfo: Elearning login, password and progress remain unchanged; a notification is thus not necessary. This is only possible for already failed learners. Note that the reset procedure may take up to 2 hours.
@ -122,7 +138,12 @@ LmsActRestart: Restart elearning
LmsActRestartWarning: The existing elearning will be erased immediately! For drivers with a valid licence, user and password will later be generated anew and a notification will be queued as usual, which may take several hours.
LmsActRestartExtend: Ensure validity for the next # days
LmsActRestartUnblock: Undo any revocations
LmsActRestartFeedback n@Int m@Int: #{n}/#{m} e-learnings were completely restarted with new login credentials.
LmsActRestartFeedback n m: #{n}/#{m} e-learnings were completely restarted with new login credentials.
LmsActTerminate: Abort elearning
LmsActTerminateInfo: Elearning may restart later, if a valid qualification is about to expire and e-learning starting automatically for this qualification.
LmsActTerminateFeedback n m: #{n}/#{m} elearnings marked for termination.
LmsActTerminated n: #{n} elearnings were terminated.
LmsActTerminateWarning: WARNING: Results will be discarded without warning if a user completes their e-learning in the meantime, before the deletion became effective on the elearning server.
LmsStateOpen: Elearning open
LmsStatusLocked: Elearning locked, may be opened soon
LmsStatusUnlocked: Elearning still open, may be locked soon
@ -134,3 +155,18 @@ LmsActionFailed n: No action for #{n} #{pluralENs n "person"}, since there was n
LmsStarted: Elearning open since
BtnLmsEnqueue: Enqueue users with expiring qualifications for elearning and notify them
BtnLmsDequeue: Dequeue users with finished elearning and notify failed users
QualificationEditNote: Changes are effective immediately. Please double check that all settings are correct before submitting the changes!
QualificationCreated qsh@Text: Qualification #{qsh} created.
QualificationEdit qsh@Text: Qualification #{qsh} edited.
QualFormErrorDuplShort qsh@Text: There already exists a qualification with shorthand #{qsh}!
QualFormErrorDuplName qname@Text: There already exists a qualification with name #{qname}!
QualFormErrorSshMismatch: Qualification edit form department mismatch. Please try again after reloading the page.
LmsOrphans: Orphaned logins
LmsOrphanNr n@Int: #{n} orphaned elearning login detected for this qualification.
LmsOrphanSeenFirst: First seen
LmsOrphanSeenLast: Last seen
LmsOrphanDeletedLast: Deletion requested
LmsOrphanReason: Note
LmsOrphanPreviewFltr: Deletion request next synch?

View File

@ -40,4 +40,6 @@ SchoolAuthorshipStatementSheetDefinitionTip: Bitte in sowohl deutscher als auch
SchoolAuthorshipStatementSheetExamDefinition: Eigenständigkeitserklärung für prüfungszugehörige Übungsblattabgaben
SchoolAuthorshipStatementSheetExamDefinitionTip: Bitte in sowohl deutscher als auch englischer Sprache angeben.
SchoolAuthorshipStatementSheetAllowOther: Abweichende Eigenständigkeitserklärungen für nicht-prüfungszugehörige Übungsblätter erlauben?
SchoolAuthorshipStatementSheetExamAllowOther: Abweichende Eigenständigkeitserklärungen für prüfungszugehörige Übungsblätter erlauben?
SchoolAuthorshipStatementSheetExamAllowOther: Abweichende Eigenständigkeitserklärungen für prüfungszugehörige Übungsblätter erlauben?
DailyActDummy: Platzhalter ohne Funktion

View File

@ -26,7 +26,7 @@ SchoolCreated ssh: Successfully created #{ssh}
SchoolExists ssh: A department named „#{ssh}“ already exists
SchoolAdmin: Admin
SchoolLecturer: Lecturer
SchoolEvaluation: Course type evaluation
SchoolEvaluation: Course category evaluation
SchoolExamOffice: Exam office
SchoolAuthorshipStatementSection: Statements of Authorship
@ -40,4 +40,6 @@ SchoolAuthorshipStatementSheetDefinitionTip: Please enter both german and englis
SchoolAuthorshipStatementSheetExamDefinition: Statement of Authorship for exam-related exercise sheets
SchoolAuthorshipStatementSheetExamDefinitionTip: Please enter both german and english statements.
SchoolAuthorshipStatementSheetAllowOther: Allow adaptations for exam-unrelated exercise sheets?
SchoolAuthorshipStatementSheetExamAllowOther: Allow adaptations for exam-related exercise sheets?
SchoolAuthorshipStatementSheetExamAllowOther: Allow adaptations for exam-related exercise sheets?
DailyActDummy: Placholder without function

View File

@ -9,17 +9,17 @@ MailCorrectionsTitle: Assigned corrections
#correctionsNotDistributed.hs + templates
MailSubjectSubmissionsUnassigned csh sheetName: Corrections for #{sheetName} of #{csh} could not be distributed
MailSubmissionsUnassignedIntro n courseName termDesc sheetName: #{n} corrections for #{sheetName} of the course type #{courseName} (#{termDesc}) could not be automatically distributed.
MailSubmissionsUnassignedIntro n courseName termDesc sheetName: #{n} corrections for #{sheetName} of the course category #{courseName} (#{termDesc}) could not be automatically distributed.
#courseRegistered.hs + templates
MailSubjectCourseRegistered csh: You were enrolled for #{csh}
MailSubjectCourseRegisteredOther displayName csh: #{displayName} was enrolled for #{csh}
MailCourseRegisteredIntro courseName termDesc: You were enrolled for the course type “#{courseName}” (#{termDesc})
MailCourseRegisteredIntroOther displayName courseName termDesc: #{displayName} was enrolled for the course type “#{courseName}” (#{termDesc}).
MailCourseRegisteredIntro courseName termDesc: You were enrolled for the course category “#{courseName}” (#{termDesc})
MailCourseRegisteredIntroOther displayName courseName termDesc: #{displayName} was enrolled for the course category “#{courseName}” (#{termDesc}).
#examActive.hs + templates
MailSubjectExamRegistrationActive csh examn: Registration is now allowed for #{examn} of #{csh}
MailExamRegistrationActiveIntro courseName termDesc examn: You may now register for #{examn} of the course type #{courseName} (#{termDesc}).
MailExamRegistrationActiveIntro courseName termDesc examn: You may now register for #{examn} of the course category #{courseName} (#{termDesc}).
MailSubjectExamRegistrationSoonInactive csh examn: The registration period for #{examn} of #{csh} ends shortly
MailExamRegistrationSoonInactiveIntro courseName termDesc examn: Soon you will no longer be allowed to register for #{examn} of #{courseName} (#{termDesc}).
MailSubjectExamDeregistrationSoonInactive csh examn: Deregistration for #{examn} in #{csh} ends shortly
@ -27,15 +27,15 @@ MailExamDeregistrationSoonInactiveIntro courseName termDesc examn: Soon you will
#examOffice.hs + templates
MailSubjectExamOfficeExamResults coursen examn: Results for #{examn} of #{coursen} are now available
MailExamOfficeExamResultsIntro courseName termDesc examn: A course administrator has made the results for #{examn} of the course type #{courseName} (#{termDesc}) available.
MailExamOfficeExamResultsIntro courseName termDesc examn: A course administrator has made the results for #{examn} of the course category #{courseName} (#{termDesc}) available.
MailSubjectExamOfficeExamResultsChanged coursen examn: Results for #{examn} of #{coursen} were changed
MailExamOfficeExamResultsChangedIntro courseName termDesc examn: A course administrator has changed exam results for #{examn} of the course type #{courseName} (#{termDesc}).
MailExamOfficeExamResultsChangedIntro courseName termDesc examn: A course administrator has changed exam results for #{examn} of the course category #{courseName} (#{termDesc}).
MailSubjectExamOfficeExternalExamResults coursen@CourseName examn@ExamName: Results for #{examn} in #{coursen}
MailExamOfficeExternalExamResultsIntro coursen@CourseName termDesc@Text examn@ExamName: A course administrator has changed or initially made available the results for #{examn} of the course type {coursen} (#{termDesc}).
MailExamOfficeExternalExamResultsIntro coursen@CourseName termDesc@Text examn@ExamName: A course administrator has changed or initially made available the results for #{examn} of the course category {coursen} (#{termDesc}).
#examOffice.hs + templates
MailSubjectExamResult csh examn: Results for #{examn} in #{csh} are now available
MailExamResultIntro courseName termDesc examn: You may now view your result for #{examn} of the course type #{courseName} (#{termDesc}).
MailExamResultIntro courseName termDesc examn: You may now view your result for #{examn} of the course category #{courseName} (#{termDesc}).
#sheetActive.hs + templates
MailSubjectSheetActive csh sheetName: #{sheetName} in #{csh} was released
@ -47,10 +47,10 @@ MailSheetSolutionIntro courseName termDesc sheetName: You may now download the s
#sheetInactive.hs + templates
MailSubjectSheetSoonInactive csh sheetName: The submission period for #{sheetName} of #{csh} ends shortly
MailSheetSoonInactiveIntro courseName termDesc sheetName: Soon you will no longer be allowed to submit for #{sheetName} of the course type #{courseName} (#{termDesc}).
MailSheetSoonInactiveIntro courseName termDesc sheetName: Soon you will no longer be allowed to submit for #{sheetName} of the course category #{courseName} (#{termDesc}).
MailSubjectSheetInactive csh sheetName: The submission period for #{sheetName} of #{csh} has ended
MailSheetInactiveIntro courseName termDesc sheetName n num: The submission period for #{sheetName} of the course type #{courseName} (#{termDesc}) has ended. #{noneOneMoreEN num "" "One participant" (toMessage num <> " participants")}#{noneOneMoreEN n "" "" (" made " <> toMessage num)}#{noneOneMoreEN n "There were no submissions" " made one submission" " submissions"}.
MailSheetInactiveIntroNoUserSubmission courseName termDesc sheetName n num: The submission period for #{sheetName} of the course type #{courseName} (#{termDesc}) has ended. #{noneOneMoreEN num "" "One participant already" (toMessage num <> " participants already")}#{noneOneMoreEN n "" "" (" made " <> toMessage num)}#{noneOneMoreEN n "" " made one submission" " submissions"}.
MailSheetInactiveIntro courseName termDesc sheetName n num: The submission period for #{sheetName} of the course category #{courseName} (#{termDesc}) has ended. #{noneOneMoreEN num "" "One participant" (toMessage num <> " participants")}#{noneOneMoreEN n "" "" (" made " <> toMessage num)}#{noneOneMoreEN n "There were no submissions" " made one submission" " submissions"}.
MailSheetInactiveIntroNoUserSubmission courseName termDesc sheetName n num: The submission period for #{sheetName} of the course category #{courseName} (#{termDesc}) has ended. #{noneOneMoreEN num "" "One participant already" (toMessage num <> " participants already")}#{noneOneMoreEN n "" "" (" made " <> toMessage num)}#{noneOneMoreEN n "" " made one submission" " submissions"}.
MailSheetInactivePseudonymsCount n: The number of submissions above accounts only for the submissions already made directly in FRADrive. #{n} #{pluralEN n "pseudonym was" "pseudonyms were"} generated.
MailSheetInactiveParticipantsCount n: There #{pluralEN n "is" "are"} currently #{n} #{pluralEN n "participant" "participants"} registered for the course.

View File

@ -14,7 +14,7 @@ AuthTagAdmin: User is administrator
AuthTagExamOffice: User is part of an exam office
AuthTagSystemExamOffice: User is charged with system wide exam administration
AuthTagSystemPrinter: User is responsible for system wide letter printing
AuthTagEvaluation: User is charged with course type evaluation
AuthTagEvaluation: User is charged with course category evaluation
AuthTagToken: User is presenting an authorisation-token
AuthTagNoEscalation: User permissions are not being expanded to other departments
AuthTagDeprecated: Page is not deprecated
@ -26,7 +26,7 @@ AuthTagTutor: User is instructor
AuthTagTutorControl: Instructors have control over their course
AuthTagTime: Time restrictions are fulfilled
AuthTagStaffTime: Time restrictions for teaching staff are fulfilled
AuthTagCourseTime: Time restrictions for course type visibility are fulfilled
AuthTagCourseTime: Time restrictions for course category visibility are fulfilled
AuthTagCourseRegistered: User is enrolled in course
AuthTagTutorialRegistered: User is course participant
AuthTagExamRegistered: User is exam participant
@ -37,11 +37,11 @@ AuthTagParticipant: User participates in course
AuthTagRegisterGroup: User is not participant in any course of the same registration group
AuthTagCapacity: Capacity is sufficient
AuthTagEmpty: Resource is “empty”
AuthTagMaterials: Course type material is publicly accessable
AuthTagMaterials: Course category material is publicly accessable
AuthTagOwner: User is owner
AuthTagPersonalisedSheetFiles: User has been assigned personalised sheet files
AuthTagRated: Submission is marked
AuthTagUserSubmissions: Submissions are made by course type participants
AuthTagUserSubmissions: Submissions are made by course category participants
AuthTagCorrectorSubmissions: Submissions are registered by correctors
AuthTagCorrectionAnonymous: Correction is anonymised
AuthTagSelf: User is only accessing their only data

View File

@ -31,7 +31,7 @@ DownloadFilesTip: When set, files are automatically treated as downloads. Otherw
WarningDays: Deadline-preview
WarningDaysTip: How many days ahead should deadlines regarding exams etc. be displayed on the homepage?
ShowSex: Show sex of other users
ShowSexTip: Should users' sex be displayed in (among others) lists of course type participants?
ShowSexTip: Should users' sex be displayed in (among others) lists of course category participants?
PDFPassword: Password to lock PDF email attachments
PDFPasswordTip: Please note that this password is displayed to FRADrive admins and is saved unencrypted
@ -53,14 +53,14 @@ UserSchoolsTip: You will only receive department-wide notifications for the sele
NotificationSettings: Desired notifications
NotificationTriggerKindAll: For all users
NotificationTriggerKindCourseParticipant: For course type participants
NotificationTriggerKindCourseParticipant: For course category participants
NotificationTriggerKindExamParticipant: For exam participants
NotificationTriggerKindCorrector: For correctors
NotificationTriggerKindLecturer: For course administrators
NotificationTriggerKindCourseLecturer: For course administrators
NotificationTriggerKindAdmin: For administrators
NotificationTriggerKindExamOffice: For the exam office
NotificationTriggerKindEvaluation: For course type evaluations
NotificationTriggerKindEvaluation: For course category evaluations
NotificationTriggerKindSubmissionUser: For participants in an exercise sheet submission
NotificationTriggerSubmissionRatedGraded: My submission for an exercise sheet was marked (not purely informational)

View File

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2022 Gregor Kleen <gregor.kleen@ifi.lmu.de>,Steffen Jost <jost@tcs.ifi.lmu.de>,Winnie Ros <winnie.ros@campus.lmu.de>
# SPDX-FileCopyrightText: 2022-25 Gregor Kleen <gregor.kleen@ifi.lmu.de>,Steffen Jost <jost@tcs.ifi.lmu.de>,Winnie Ros <winnie.ros@campus.lmu.de>,Steffen Jost <s.jost@fraport.de>
#
# SPDX-License-Identifier: AGPL-3.0-or-later
@ -19,19 +19,25 @@ ProfileSubmissionGroups: Abgabegruppen
ProfileSubmissions: Abgaben
ProfileRemark: Hinweis
ProfileQualifications: Eigene Qualifikationen
ProfileEnrolledExams: Angemeldete Prüfungen
PersonalInfoExamAchievementsWip: Die Anzeige von Prüfungsergebnissen wird momentan an dieser Stelle leider noch nicht unterstützt.
PersonalInfoOwnTutorialsWip: Die Anzeige von Kurse, zu denen Sie als Ausbilder eingetragen sind wird momentan an dieser Stelle leider noch nicht unterstützt.
PersonalInfoTutorialsWip: Die Anzeige von Kurse, zu denen Sie angemeldet sind wird momentan an dieser Stelle leider noch nicht unterstützt.
ProfileGroupSubmissionDates: Bei Gruppenabgaben wird kein Datum angezeigt, wenn Sie die Gruppenabgabe nie selbst hochgeladen haben.
ProfileCorrectorRemark: Die oberhalb angezeigte Tabelle zeigt nur prinzipielle Einteilungen als Korrektor zu einem Übungsblatt. Auch ohne Einteilung können Korrekturen einzeln zugewiesen werden, welche hier dann nicht aufgeführt werden.
ProfileCorrections: Auflistung aller zugewiesenen Korrekturen
Remarks: Hinweise
Remarks: Hinweis:
ProfileSupervisor: Übergeordnete Ansprechpartner
ProfileSupervisee: Ist Ansprechpartner für
ProfileNoSupervisor: Keine übergeordneten Ansprechpartner vorhanden
ProfileSupervisor n@Int m@Int: #{n} #{pluralDE n "übergeordneter" "übergeordnete"} Ansprechpartner#{noneMoreDE m "" (", davon " <> tshow m <> " mit Benachrichtigungsumleitung")}
ProfileSupervisorRemark n@Int m@Int l@Int: #{m} von #{n} #{pluralDE m "übergeordneter" "übergeordnete"} Ansprechpartner mit Benachrichtigungsumleitung#{noneMoreDE l "" (", davon " <> tshow l <> " mit postalischer Benachrichtigung")}
ProfileNoSupervisee: Ist kein Ansprechpartner für irgendjemand
ProfileSupervisee n@Int m@Int: Ist Ansprechpartner für #{n} #{pluralDE n "Person" "Personen"}#{noneMoreDE m "" (", davon " <> tshow m <> " mit Benachrichtigungsumleitung")}
ProfileSuperviseeRemark n@Int m@Int: Dieser Nutzer ist Ansprechpartner für #{n} #{pluralDE n "Person" "Personen"}#{noneMoreDE m "" (", davon " <> tshow m <> " mit Benachrichtigungsumleitung")}
UserTelephone: Telefon
UserMobile: Mobiltelefon
Company: Firmenzugehörigkeit
CompanyPersonalNumber: Personalnummer (nur Fraport AG)
CompanyPersonalNumber: Personalnummer
CompanyPersonalNumberFraport: Personalnummer (nur Fraport AG)
CompanyDepartment: Abteilung

View File

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2022 Steffen Jost <jost@tcs.ifi.lmu.de>,Winnie Ros <winnie.ros@campus.lmu.de>
# SPDX-FileCopyrightText: 2022-25 Steffen Jost <jost@tcs.ifi.lmu.de>,Winnie Ros <winnie.ros@campus.lmu.de>,Steffen Jost <s.jost@fraport.de>
#
# SPDX-License-Identifier: AGPL-3.0-or-later
@ -11,7 +11,7 @@ LastLogin: Last login
NeverSet: Never
ProfileCorrector: Corrector
ProfileCourses: Own courses
ProfileCourseParticipations: Course type registrations
ProfileCourseParticipations: Course category registrations
ProfileCourseExamResults: Exam achievements
ProfileTutorials: Own courses
ProfileTutorialParticipations: Courses
@ -19,19 +19,25 @@ ProfileSubmissionGroups: Submission groups
ProfileSubmissions: Submissions
ProfileRemark: Remarks
ProfileQualifications: Owned Qualifications
ProfileEnrolledExams: Enrolled Exams
PersonalInfoExamAchievementsWip: The feature to display your exam achievements has not yet been implemented.
PersonalInfoOwnTutorialsWip: The feature to display courses you have been assigned to as instructor has not yet been implemented.
PersonalInfoTutorialsWip: The feature to display courses you have registered for has not yet been implemented.
ProfileGroupSubmissionDates: No date is shown for group submissions if you have never uploaded the submission yourself.
ProfileCorrectorRemark: The table above only shows registration as a corrector in principle. Even without registration corrections can be assigned individually and are not listed.
ProfileCorrections: List of all assigned corrections
Remarks: Remarks
Remarks: Remark:
ProfileSupervisor: Supervised by
ProfileSupervisee: Supervises
ProfileNoSupervisor: Is not supervised by anynone
ProfileSupervisor n m: #{pluralENsN n "supervisor"} #{noneMoreEN m "" ("with " <> tshow m <> " active notification rerouting")}
ProfileSupervisorRemark n@Int m@Int l@Int: #{m} of #{n} #{pluralENs m "supervisor"} with active notification rerouting#{noneMoreEN l "" (", and " <> tshow l <> "of these prefer postal notifications")}
ProfileNoSupervisee: Does not supervise anynone
ProfileSupervisee n m: Supervises #{pluralENsN n "person"} #{noneMoreEN m "" ("with " <> tshow m <> " active notification rerouting")}
ProfileSuperviseeRemark n m: This person supervises #{pluralENsN n "person"}#{noneMoreEN m "" (" with " <> tshow m <> " having active notifications rerouting to this user")}
UserTelephone: Phone
UserMobile: Mobile
Company: Company affilitaion
CompanyPersonalNumber: Personnel number (Fraport AG only)
Company: Company affiliation
CompanyPersonalNumber: Personnel number
CompanyPersonalNumberFraport: Personnel number (Fraport AG only)
CompanyDepartment: Department

View File

@ -22,6 +22,7 @@ AdminUserPostAddress: Postalische Anschrift
AdminUserPrefersPostal: Briefe anstatt Email bevorzugt
AdminUserPinPassword: Passwort zur Verschlüsselung von PDF Anhängen in Emails
AdminUserNoPassword: Kein Passwort gesetzt
AdminUserPinPassNotIncluded: Hinweis: Das Passwort wird hier zur Bequemlichkeit zusätzlich angezeigt und ist selbstverständlich nicht im originalem Inhalt enthalten.
AdminUserAssimilate: Diesen Benutzer assimilieren von
UserAdded: Benutzer erfolgreich angelegt
UserCollision: Benutzer konnte wegen Eindeutigkeit nicht angelegt werden
@ -37,10 +38,12 @@ AuthPWHashAlreadyConfigured: Nutzer:in meldet sich bereits mit FRADrive spezifis
AuthPWHashConfigured: Nutzer:in meldet sich nun mit FRADrive spezifischer Kennung an
UsersCourseSchool: Bereich
ActionNoUsersSelected: Keine Benutzer:innen ausgewählt
SynchroniseAvsUserQueued n@Int: AVS-Synchronisation von #{n} #{pluralDE n "Benutzer:in" "Benutzer:innen"} angestoßen
SynchroniseLdapUserQueued n@Int: LDAP-Synchronisation von #{n} #{pluralDE n "Benutzer:in" "Benutzer:innen"} angestoßen
SynchroniseLdapAllUsersQueued: LDAP-Synchronisation von allen Benutzer:innen angestoßen
SynchroniseAvsUserQueued n@Int: AVS-Synchronisation von #{n} #{pluralDE n "Benutzer:in" "Benutzer:innen"} zwingend angestoßen, die Ausführung wird mehrere Minuten benötigen!
SynchroniseAvsAllUsersQueued n@Int64: AVS-Synchronisation von allen #{n} #{pluralDE n "Benutzer:in" "Benutzer:innen"} angestoßen, welche heute noch nicht synchronisiert wurden, die Ausführung wird eine Weile brauchen!
SynchroniseLdapUserQueued n@Int: LDAP-Synchronisation von #{n} #{pluralDE n "Benutzer:in" "Benutzer:innen"} angestoßen, die Ausführung wird mehrere Minuten benötigen!
SynchroniseLdapAllUsersQueued: LDAP-Synchronisation von allen Benutzer:innen angestoßen, die Ausführung kann eine Weile brauchen!
UserListTitle: Komprehensive Benutzerliste
UserRecipientsTitle name@Text: Benachrichtigungsempfänger für #{name}
AccessRightsSaved: Berechtigungen erfolgreich verändert
AccessRightsNotChanged: Berechtigungen wurden nicht verändert
AuthLDAPLookupFailed: Nutzer:in konnte aufgrund eines LDAP-Fehlers nicht nachgeschlagen werden
@ -89,12 +92,19 @@ NewPasswordLink: Neues Passwort setzen
UserAccountDeleteWarning: Achtung, dies löscht den kompletten Benutzer/die komplette Benutzerin unwiderruflich und mit allen assoziierten Daten aus der Datenbank. Prüfungsdaten müssen jedoch langfristig gespeichert bleiben!
UserAvsSync: AVS-Synchronisieren
UserLdapSync: LDAP-Synchronisieren
AllUsersLdapSync: Alle LDAP-Synchronisieren
UserHijack: Sitzung übernehmen
UserAddSupervisor: Ansprechpartner hinzufügen
UserSetSupervisor: Ansprechpartner ersetzen
UserRemoveSupervisor: Alle Ansprechpartner entfernen
UserRemoveClients: Alle Ansprechpartnerbeziehungen zu Klienten beenden
UserIsSupervisor: Ist Ansprechpartner
UserAvsSwitchCompany: Als Primärfirma verwenden
UserAvsSwitchCompanyField: Primärfirma auswählen
UserAvsCompanySwitched c@CompanyShorthand: Primärfirma gewechselt zu #{tshow c}
AllUsersLdapSync: Alle LDAP-Synchronisieren
AllUsersAvsSync: Alle AVS-Synchronisieren
ThisUserLdapSync: LDAP Synchronisation
ThisUserAvsSync: AVS Synchronisation
AuthKindLDAP: Fraport AG Kennung
AuthKindPWHash: FRADrive Kennung
AuthKindNoLogin: Kein Login möglich
@ -102,3 +112,10 @@ Name !ident-ok: Name
UsersChangeSupervisorsSuccess usr@Int spr@Int: #{tshow spr} Ansprechpartner für #{tshow usr} Benutzer gesetzt.
UsersChangeSupervisorsWarning usr@Int spr@Int bad@Int: Nur _{MsgUsersChangeSupervisorsSuccess usr spr} #{tshow bad} Ansprechpartner #{pluralDE bad "wurde" "wurden"} nicht gefunden!
UsersRemoveSupervisors usr@Int: Alle Ansprechpartner für #{tshow usr} Benutzer gelöscht.
UsersRemoveClients usr@Int: Alle Ansprechpartnerbeziehungen für #{tshow usr} #{pluralDE usr "ehemaligen" "ehemalige"} Ansprechpartner gelöscht.
UserCompanyReason: Begründung der Firmenassoziation
UserCompanyReasonTooltip: Optionale Notiz für besondere Fälle. Kann ggf. autmatische Entfernung bei AVS Firmenwechsel verhindern.
UserSupervisorReason: Begründung Ansprechpartner
UserSupervisorReasonTooltip: Optionale Notiz für besondere Fälle. Kann ggf. autmatische Entfernung bei AVS Firmenwechsel verhindern.
UserSupervisorCompany: Ansprechpartner wegen Firma
AdminUserAllNotifications: Alle Benachrichtigungen and diesen Benutzer

View File

@ -22,6 +22,7 @@ AdminUserPostAddress: Postal Address
AdminUserPrefersPostal: Prefers postal letters over email
AdminUserPinPassword: Password used for PDF attachments to emails
AdminUserNoPassword: No password set
AdminUserPinPassNotIncluded: Note: the password is shown here only for convenience, but is not contained in the original content, of course.
AdminUserAssimilate: Assimilate user by another user
UserAdded: Successfully added user
UserCollision: Could not create user due to uniqueness constraint
@ -37,10 +38,12 @@ AuthPWHashAlreadyConfigured: User already logs in using their FRADrive specific
AuthPWHashConfigured: User now logs in using their FRADrive specific account
UsersCourseSchool: Department
ActionNoUsersSelected: No users selected
SynchroniseAvsUserQueued n: Triggered AVS synchronisation of #{n} #{pluralEN n "user" "users"}.
SynchroniseLdapUserQueued n: Triggered LDAP synchronisation of #{n} #{pluralEN n "user" "users"}.
SynchroniseLdapAllUsersQueued: Triggered LDAP synchronisation of all users
SynchroniseAvsUserQueued n: Triggered forced AVS synchronisation of #{n} #{pluralEN n "user" "users"}, which may take several minutes to complete.
SynchroniseAvsAllUsersQueued n: Triggered AVS synchronisation of all #{n} #{pluralEN n "user" "users"} that were not already synchronised today, which may take quite a while to complete.
SynchroniseLdapUserQueued n: Triggered LDAP synchronisation of #{n} #{pluralEN n "user" "users"}, which may take several minutes to complete.
SynchroniseLdapAllUsersQueued: Triggered LDAP synchronisation of all users, which may take quite a while to complete.
UserListTitle: Comprehensive list of users
UserRecipientsTitle name: Notificationrecipients for #{name}
AccessRightsSaved: Successfully updated permissions
AccessRightsNotChanged: Permissions left unchanged
AuthLDAPLookupFailed: User could not be looked up due to a LDAP error
@ -89,16 +92,30 @@ NewPasswordLink: Set password
UserAccountDeleteWarning: Caution, this permanently deletes users and all of their associated data. Exam results must be stored long term!
UserAvsSync: Synchronise with AVS
UserLdapSync: Synchronise with LDAP
AllUsersLdapSync: Synchronise all with LDAP
UserHijack: Hijack session
UserAddSupervisor: Add supervisor
UserSetSupervisor: Replace supervisors
UserRemoveSupervisor: Set to unsupervised
UserRemoveClients: Remove all clients
UserIsSupervisor: Is supervisor
UserAvsSwitchCompany: Use as primary company
UserAvsSwitchCompanyField: Select primary company
UserAvsCompanySwitched c: Primary company switched to #{tshow c}
AllUsersLdapSync: Synchronise all with LDAP
AllUsersAvsSync: Synchronise all with AVS
ThisUserLdapSync: Synchronise user with LDAP
ThisUserAvsSync: Synchronise user with AVS
AuthKindLDAP: Fraport AG account
AuthKindPWHash: FRADrive account
AuthKindNoLogin: No login
Name: Name
UsersChangeSupervisorsSuccess usr spr: #{pluralENsN spr "supervisor"} for #{pluralENsN usr "user"} set.
UsersChangeSupervisorsWarning usr spr bad: Only _{MsgUsersChangeSupervisorsSuccess usr spr} #{pluralENsN bad "supervisors"} could not be identified!
UsersRemoveSupervisors usr: Removed all supervisors for #{pluralENsN usr "user"}.
UsersRemoveSupervisors usr: Removed all supervisors for #{pluralENsN usr "user"}.
UsersRemoveClients usr: Removed all clients for #{pluralENsN usr "previous supervisor"}.
UserCompanyReason: Reason for company association
UserCompanyReasonTooltip: Optional note for special cases. In some case this may prevent automatic removel upon AVS user company changes.
UserSupervisorReason: Reason for supervision
UserSupervisorReasonTooltip: Optional note for special cases. In some case this may prevent automatic removel upon AVS user company changes.
UserSupervisorCompany: Supervisor for company
AdminUserAllNotifications: All notification sent to this user

View File

@ -4,24 +4,42 @@
#messages or constructors that are used all over the code
Logo !ident-ok: Uni2work
EmailInvitationWarning: Diese Adresse konnte keinem Uni2work-Benutzer/keiner Uni2work-Benutzerin zugeordnet werden. Es wird eine Einladung per E-Mail versandt.
Logo !ident-ok: FRADrive
LdapIdentificationOrEmail: Fraport AG-Kennung / E-Mail-Adresse
EmailInvitationWarning: Diese Adresse konnte keinem FRADrive-Benutzer/-Benutzerin zugeordnet werden. Es wird eine Einladung per E-Mail versandt.
BoolIrrelevant !ident-ok: —
FieldPrimary: Hauptfach
FieldSecondary: Nebenfach
MultiEmailFieldTip: Es sind mehrere, Komma-separierte, E-Mail-Adressen möglich
MultiSelectTip: Mehrfachauswahl und Abwählen mit Strg-Klick
WeekDay: Wochentag
LdapIdentificationOrEmail: Fraport AG-Kennung / E-Mail-Adresse
Hours: Stunden
SomeMonths: Monate
SomeDays: Tage
Months num@Int64: #{num} #{pluralDE num "Monat" "Monate"}
Days num@Int64: #{num} #{pluralDE num "Tag" "Tage"}
NoAutomaticUpdateTip: Dieser Wert wurde manuell editiert und wird daher nicht mehr automatisch durch as AVS aktualisiert.
AddressIsLinkedTip: Verlinkte Postaddresse: Für diesen Benutzer ist keine individuelle Postadresse gespeichert, die Adresse wurde stattdessen aus der Firmenzugehörigkeit abgeleitet.
ClusterVolatileQuickActionsEnabled: Schnellzugriffsmenü aktiv
AvsNoLicence: Keine Fahrberechtigung
AvsLicenceVorfeld: Vorfeld Fahrberechtigung
AvsLicenceRollfeld: Rollfeld Fahrberechtigung
AvsNoLicenceGuest: Keine Fahrberechtigung (Gast, Fahrberechtigungserwerb nicht möglich)
PaginationSize: Einträge pro Seite
PaginationPage: Angzeigte Seite
PaginationError: Paginierung Parameter dürfen nicht negativ sein
PaginationError: Paginierung Parameter dürfen nicht negativ sein
NullDeletes: Zum Löschen NULL eingeben.
SortPriority: Sortierungspriorität
NoProblem: Keine Probleme gefunden
Unknown: ist unbekannt
UnknownOrNotAllowed: ist unbekannt oder hier nicht erlaubt
Ambiguous: ist uneindeutig
Action: Aktion
For: für
Address: Adresse
NoContactAddress: Keinerlei Kontaktdaten bekannt!
StarKeepsEmptyDeletes: Stern zum Beibehalten, leer lassen zum Löschen

View File

@ -4,24 +4,42 @@
#messages or constructors that are used all over the Code
Logo: Uni2work
EmailInvitationWarning: This address could not be matched to any Uni2work user. An invitation will be sent via email.
Logo: FRADrive
LdapIdentificationOrEmail: Fraport AG-Kennung / email address
EmailInvitationWarning: This address could not be matched to any FRADrive user. An invitation will be sent via email.
BoolIrrelevant: —
FieldPrimary: Major
FieldSecondary: Minor
MultiEmailFieldTip: Multiple emails addresses may be specified (comma-separated)
MultiSelectTip: Multiple selection and desection via Ctrl-Click
WeekDay: Day of the week
LdapIdentificationOrEmail: Fraport AG-Kennung / email address
Hours: Hours
SomeMonths: Months
SomeDays: Days
Months num: #{num} #{pluralEN num "Month" "Months"}
Days num: #{num} #{pluralEN num "Day" "Days"}
NoAutomaticUpdateTip: This particular value receives no automatic AVS updates, since it has been edited manually.
AddressIsLinkedTip: Linked postal address: No individual postal address is stored for this user, instead a postal address was inferred from the user's company association.
ClusterVolatileQuickActionsEnabled: Quick actions enabled
AvsNoLicence: No driving licence
AvsLicenceVorfeld: Apron driving licence
AvsLicenceRollfeld: Maneuvering area driving licence
AvsNoLicenceGuest: No driving licence (Guest account, cannot acquire a diriving licence)
PaginationSize: Rows per Page
PaginationPage: Page to show
PaginationError: Pagination parameter must not be negative
PaginationError: Pagination parameter must not be negative
NullDeletes: Enter NULL to delete.
SortPriority: Sort order priority
NoProblem: No Probleme found
Unknown: is unknown
UnknownOrNotAllowed: is unknown or not allowed here
Ambiguous: is ambiguous
Action: Action
For: for
Address: Address
NoContactAddress: No contact details known!
StarKeepsEmptyDeletes: A star to keep unchanged, blank removes

View File

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2022 Gregor Kleen <gregor.kleen@ifi.lmu.de>,Steffen Jost <jost@tcs.ifi.lmu.de>,Winnie Ros <winnie.ros@campus.lmu.de>,Sarah Vaupel <sarah.vaupel@ifi.lmu.de>
# SPDX-FileCopyrightText: 2022-24 Gregor Kleen <gregor.kleen@ifi.lmu.de>,Steffen Jost <jost@tcs.ifi.lmu.de>,Winnie Ros <winnie.ros@campus.lmu.de>,Sarah Vaupel <sarah.vaupel@ifi.lmu.de>,Steffen Jost <s.jost@fraport.de>
#
# SPDX-License-Identifier: AGPL-3.0-or-later
@ -55,6 +55,8 @@ BtnUserAssimilate: Assimilieren
BtnCloseExam: Prüfung abschließen
BtnFinishExam: Prüfungsergebnisse sichtbar schalten
BtnConfirm: Bestätigen
BtnPerform: Ausführen
BtnCourseRegisterAdd: Personen suchen
BtnCourseRegisterConfirm: Ausgewählte Personen anmelden
BtnCourseRegisterAbort: Abbrechen
BtnCourseRegisterAbort: Abbrechen
BtnCloseReload: Schließen und aktualisieren

View File

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2022 Steffen Jost <jost@tcs.ifi.lmu.de>,Winnie Ros <winnie.ros@campus.lmu.de>,Sarah Vaupel <sarah.vaupel@ifi.lmu.de>
# SPDX-FileCopyrightText: 2022-24 Steffen Jost <jost@tcs.ifi.lmu.de>,Winnie Ros <winnie.ros@campus.lmu.de>,Sarah Vaupel <sarah.vaupel@ifi.lmu.de>,Steffen Jost <s.jost@fraport.de>
#
# SPDX-License-Identifier: AGPL-3.0-or-later
@ -55,6 +55,8 @@ BtnUserAssimilate: Assimilate
BtnCloseExam: Close exam
BtnFinishExam: Make results visible
BtnConfirm: Confirm
BtnPerform: Perform
BtnCourseRegisterAdd: Search persons
BtnCourseRegisterConfirm: Register selected persons
BtnCourseRegisterAbort: Abort
BtnCourseRegisterAbort: Abort
BtnCloseReload: Close and reload

View File

@ -20,3 +20,7 @@ ExceptionNoOccurAt: Termin
ExceptionKind: Termin ...
ExceptionKindOccur: Findet statt
ExceptionKindNoOccur: Findet nicht statt
DayNext: Folgetag
DayPrev: Vortag
WeekNext: Nächste Woche
WeekPrev: Vorherige Woche

View File

@ -20,3 +20,7 @@ ExceptionNoOccurAt: Event
ExceptionKind: Event ...
ExceptionKindOccur: Does occur
ExceptionKindNoOccur: Does not occur
DayNext: Next day
DayPrev: Previous day
WeekNext: Next week
WeekPrev: Previous week

View File

@ -71,6 +71,7 @@ BreadcrumbError: Fehler
BreadcrumbUpload !ident-ok: Upload
BreadcrumbUserAdd: Benutzer:in anlegen
BreadcrumbUserNotifications: Benachrichtigungs-Einstellungen
BreadcrumbUserRecipients: Benachrichtigungs-Empfänger
BreadcrumbUserPassword: Passwort
BreadcrumbAdminHeading !ident-ok: Administration
BreadcrumbAdminFeaturesHeading: Studiengänge

View File

@ -6,7 +6,7 @@ BreadcrumbCsvOptions: csv-options
BreadcrumbSubmissionFile: File
BreadcrumbSubmissionUserInvite: Invitation to participate in a submission
BreadcrumbCryptoIDDispatch: CryptoID-redirect
BreadcrumbCourseNotes: Course type notes
BreadcrumbCourseNotes: Course category notes
BreadcrumbHiWis: Correctors
BreadcrumbMaterial: Material
BreadcrumbSheet: Exercise sheet
@ -14,7 +14,7 @@ BreadcrumbTutorial: Course
BreadcrumbExam: Exam
BreadcrumbCourseRegister: Register
BreadcrumbCourseFavourite: Favourite
BreadcrumbCourse: Course type
BreadcrumbCourse: Course category
BreadcrumbTerm: Year
BreadcrumbSchool: Department
BreadcrumbUser: User
@ -28,11 +28,11 @@ BreadcrumbUserDelete: Delete user account
BreadcrumbUserHijack: Hijack user session
BreadcrumbSystemMessage: System message
BreadcrumbSubmission: Submission
BreadcrumbCourseNews: Course type news
BreadcrumbCourseNewsDelete: Delete course type news
BreadcrumbCourseEventDelete: Delete course type occurrence
BreadcrumbCourseNews: Course category news
BreadcrumbCourseNewsDelete: Delete course category news
BreadcrumbCourseEventDelete: Delete course category occurrence
BreadcrumbProfile: Settings
BreadcrumbCourseParticipantInvitation: Invitation to be a course type participant
BreadcrumbCourseParticipantInvitation: Invitation to be a course category participant
BreadcrumbMaterialArchive: Archive
BreadcrumbMaterialFile: File
BreadcrumbMaterialVideo: Video
@ -57,8 +57,8 @@ BreadcrumbExternalExamUsers: Participants
BreadcrumbExternalExamGrades: Exam results
BreadcrumbExternalExamStaffInvite: Invitation
BreadcrumbExternalExamCorrect: Enter exam results
BreadcrumbParticipantsList: Lists of course type participants
BreadcrumbParticipants: Course type participants
BreadcrumbParticipantsList: Lists of course category participants
BreadcrumbParticipants: Course category participants
BreadcrumbExamAutoOccurrence: Automatic occurrence/room distribution
BreadcrumbStorageKey: Generate storage key
BreadcrumbMessageHide: Hide
@ -71,6 +71,7 @@ BreadcrumbError: Error
BreadcrumbUpload: Upload
BreadcrumbUserAdd: Add user
BreadcrumbUserNotifications: Notification settings
BreadcrumbUserRecipients: Notification recipients
BreadcrumbUserPassword: Password
BreadcrumbAdminHeading: Administration
BreadcrumbAdminFeaturesHeading: Features of study
@ -96,7 +97,7 @@ BreadcrumbTermShow: Years
BreadcrumbTermCreate: Create new year
BreadcrumbTermEdit: Edit year
BreadcrumbTermCurrent: Current year
BreadcrumbParticipantsIntersect: Common course type participants
BreadcrumbParticipantsIntersect: Common course category participants
BreadcrumbCourseList: Courses
BreadcrumbCourseNew: Create new course
BreadcrumbCourseEdit: Edit course
@ -105,14 +106,14 @@ BreadcrumbCourseAddMembers: Add participants
BreadcrumbCourseExamOffice: Exam offices
BreadcrumbCorrectionsAssign: Assign corrections
BreadcrumbSheetList: Exercise sheets
BreadcrumbCourseCommunication: Course type message (email)
BreadcrumbCourseCommunication: Course category message (email)
BreadcrumbTutorialList: Courses
BreadcrumbTutorialNew: Create new course
BreadcrumbCourseDelete: Delete course
BreadcrumbCourseNewsNew: Add course type news
BreadcrumbCourseNewsEdit: Edit course type news
BreadcrumbCourseEventNew: New course type occurrence
BreadcrumbCourseEventEdit: Edit course type occurrence
BreadcrumbCourseNewsNew: Add course category news
BreadcrumbCourseNewsEdit: Edit course category news
BreadcrumbCourseEventNew: New course category occurrence
BreadcrumbCourseEventEdit: Edit course category occurrence
BreadcrumbExamList: Exams
BreadcrumbExamNew: Create new exam
BreadcrumbExamEdit: Edit exam
@ -122,7 +123,7 @@ BreadcrumbExamAddMembers: Add exam participants
BreadcrumbExamCorrect: Grade exams
BreadcrumbTutorialDelete: Delete course
BreadcrumbTutorialEdit: Edit course
BreadcrumbTutorialComm: Send course type message
BreadcrumbTutorialComm: Send course category message
BreadcrumbSheetEdit: Edit exercise sheet
BreadcrumbSheetDelete: Delete exercise sheet
BreadcrumbSubmissions: Submissions

View File

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2022 Gregor Kleen <gregor.kleen@ifi.lmu.de>,Sarah Vaupel <sarah.vaupel@ifi.lmu.de>,Steffen Jost <jost@cip.ifi.lmu.de>,Steffen Jost <jost@tcs.ifi.lmu.de>,Winnie Ros <winnie.ros@campus.lmu.de>
# SPDX-FileCopyrightText: 2022-25 Gregor Kleen <gregor.kleen@ifi.lmu.de>,Sarah Vaupel <sarah.vaupel@ifi.lmu.de>,Steffen Jost <jost@cip.ifi.lmu.de>,Steffen Jost <jost@tcs.ifi.lmu.de>,Winnie Ros <winnie.ros@campus.lmu.de>,Steffen Jost <s.jost@fraport.de>
#
# SPDX-License-Identifier: AGPL-3.0-or-later
@ -33,6 +33,7 @@ MenuCourseIcon: Kurse
MenuCourseMembers: Kursartteilnehmer:innen
MenuCourseAddMembers: Kursartteilnehmer:innen hinzufügen
MenuTutorialAddMembers: Kursteilnehmer:innen hinzufügen
MenuTutorialExam exn@ExamName: Kursprüfung #{exn} bearbeiten
MenuCourseCommunication: Kursartmitteilung (EMail)
MenuCourseExamOffice: Prüfungsbeauftragte
MenuTermShow: Jahr
@ -87,6 +88,7 @@ MenuTutorialComm: Mitteilung an Teilnehmer:innen
MenuExamList: Prüfungen
MenuExamNew: Neue Prüfung anlegen
MenuExamEdit: Prüfung bearbeiten
MenuExamEditComplete: Prüfung vollständig überarbeiten
MenuExamUsers: Teilnehmer:innen
MenuExamGrades: Prüfungsleistungen
MenuExamAddMembers: Prüfungsteilnehmer hinzufügen
@ -97,6 +99,8 @@ MenuExamOfficeUsers: Benutzer:innen
MenuLecturerInvite: Funktionäre hinzufügen
MenuSchoolList: Bereiche
MenuSchoolNew: Neuen Bereich anlegen
MenuSchoolDay ssh@SchoolId d@Text: #{d} #{unSchoolKey ssh} Tagesansicht
MenuSchoolDayCheck: Konsistenzprüfung
MenuExternalExamGrades: Prüfungsleistungen
MenuExternalExamUsers: Teilnehmer:innen
MenuExternalExamEdit: Bearbeiten
@ -119,8 +123,9 @@ MenuCourseEventEdit: Kursarttermin bearbeiten
MenuLanguage: Sprache
MenuQualifications: Qualifikationen
MenuQualificationEdit: Bearbeiten
MenuQualificationNew: Neue Qualifikation erstellen
MenuLms !ident-ok: ELearning
MenuLmsEdit: Bearbeiten ELearning
MenuLmsUser: Benutzerqualifikationen
MenuLmsUserSchool: Bereichs Benutzerqualifikationen
MenuLmsUserAll: Alle Benutzerqualifikationen
@ -136,6 +141,7 @@ MenuFirms: Firmen
MenuFirmUsers: Angehörige
MenuFirmSupervisors: Ansprechpartner
MenuFirmsComm: Mitteilung
MenuFirmsSupervision: Probleme Ansprechpartnerbeziehungen
MenuInterfaces: Schnittstellen
MenuSap: SAP Schnittstelle
@ -143,12 +149,18 @@ MenuSap: SAP Schnittstelle
MenuAvs: AVS Schnittstelle
MenuAvsSynchError: AVS Problemübersicht
MenuLdap: LDAP Schnittstelle
MenuApc: Druckerei
MenuApc: Druck
MenuPrintSend: Manueller Briefversand
MenuPrintDownload: Brief herunterladen
MenuPrintLog: LPR Schnittstelle
MenuPrintAck: Druckbestätigung
MenuCommCenter: Benachrichtigungen
MenuMailCenter: EMails
MenuMailHtml !ident-ok: Html
MenuMailPlain !ident-ok: Text
MenuMailAttachment: Anhang
MenuApiDocs: API-Dokumentation (Englisch)
MenuSwagger !ident-ok: OpenAPI 2.0 (Swagger)

View File

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2022 Gregor Kleen <gregor.kleen@ifi.lmu.de>,Sarah Vaupel <sarah.vaupel@ifi.lmu.de>,Steffen Jost <jost@tcs.ifi.lmu.de>,Winnie Ros <winnie.ros@campus.lmu.de>
# SPDX-FileCopyrightText: 2022-25 Gregor Kleen <gregor.kleen@ifi.lmu.de>,Sarah Vaupel <sarah.vaupel@ifi.lmu.de>,Steffen Jost <jost@tcs.ifi.lmu.de>,Winnie Ros <winnie.ros@campus.lmu.de>,Steffen Jost <s.jost@fraport.de>
#
# SPDX-License-Identifier: AGPL-3.0-or-later
@ -6,7 +6,7 @@ MenuAdminHeading: Administration
MenuAdminFeaturesHeading: Features of study
MenuInfoLecturerTitle: Information for course administrators
MenuInfoLecturerCourses: Courses
MenuInfoLecturerExercises: Course type Exercises
MenuInfoLecturerExercises: Course category Exercises
MenuInfoLecturerTutorials: Courses
MenuInfoLecturerExams: Exams
MenuCsvOptions: CSV-options
@ -28,12 +28,13 @@ MenuHelp: Support
MenuProfile: Settings
MenuLogin: Login
MenuLogout: Logout
MenuCourseList: Course types
MenuCourseList: Course categorys
MenuCourseIcon: Courses
MenuCourseMembers: Participants
MenuCourseAddMembers: Add course type participants
MenuCourseAddMembers: Add course category participants
MenuTutorialAddMembers: Add course participants
MenuCourseCommunication: Course type message (email)
MenuTutorialExam exn@ExamName: Edit course exam #{exn}
MenuCourseCommunication: Course category message (email)
MenuCourseExamOffice: Exam offices
MenuTermShow: Semesters
MenuSubmissionDelete: Delete submission
@ -48,7 +49,7 @@ MenuAdminErrMsg: Decrypt error message
MenuAdminTokens: Issue tokens
MenuProfileData: Personal information
MenuTermCreate: Create new year
MenuCourseNew: Create new course type
MenuCourseNew: Create new course category
MenuTermEdit: Edit year
MenuTermCurrent: Current year
MenuCorrection: Correction
@ -83,10 +84,11 @@ MenuCorrectionsAssignSheet name: Assign corrections for #{name}
MenuAuthPreds: Authorisation settings
MenuTutorialDelete: Delete course
MenuTutorialEdit: Edit course
MenuTutorialComm: Send course type message
MenuTutorialComm: Send course category message
MenuExamList: Exams
MenuExamNew: Create new exam
MenuExamEdit: Edit exam
MenuExamEditComplete: Revise entire exam
MenuExamUsers: Participants
MenuExamGrades: Exam results
MenuExamAddMembers: Add exam participants
@ -97,14 +99,16 @@ MenuExamOfficeUsers: Users
MenuLecturerInvite: Add functionaries
MenuSchoolList: Departments
MenuSchoolNew: Create new department
MenuSchoolDay ssh d: #{d} #{unSchoolKey ssh} Agenda
MenuSchoolDayCheck: Consistence check
MenuExternalExamGrades: Exam results
MenuExternalExamUsers: Participants
MenuExternalExamEdit: Edit
MenuExternalExamNew: New external exam
MenuExternalExamList: External exams
MenuExternalExamCorrect: Enter exam results
MenuParticipantsList: Lists of course type participants
MenuParticipantsIntersect: Common course type participants
MenuParticipantsList: Lists of course category participants
MenuParticipantsIntersect: Common course category participants
MenuFaq: FAQ
MenuSheetPersonalisedFiles: Download personalised sheet files
MenuCourseSheetPersonalisedFiles: Download template for personalised sheet files
@ -112,17 +116,18 @@ MenuAdminCrontab: Crontab
MenuAdminJobs: Job queue
MenuGlossary: Glossary
MenuVersion: Version history
MenuCourseNewsNew: Add course type news
MenuCourseNewsEdit: Edit course type news
MenuCourseEventNew: New course type occurrence
MenuCourseEventEdit: Edit course type occurrence
MenuCourseNewsNew: Add course category news
MenuCourseNewsEdit: Edit course category news
MenuCourseEventNew: New course category occurrence
MenuCourseEventEdit: Edit course category occurrence
MenuLanguage: Language
MenuQualifications: Qualifications
MenuQualificationEdit: Edit
MenuQualificationNew: Create new qualification
MenuLms: Elearning
MenuLmsEdit: Edit elearning
MenuLmsUser: User Qualifications
MenuLmsUserSchool: Institute User Qualifications
MenuLmsUserSchool: Department User Qualifications
MenuLmsUserAll: All User Qualifications
MenuLmsUsers: Legacy download elearning users
MenuLmsUpload: Upload
@ -136,6 +141,7 @@ MenuFirms: Companies
MenuFirmUsers: Associates
MenuFirmSupervisors: Supervisors
MenuFirmsComm: Messaging
MenuFirmsSupervision: Problems supervisionship
MenuInterfaces: Interfaces
MenuSap: SAP Interface
@ -143,12 +149,18 @@ MenuSap: SAP Interface
MenuAvs: AVS Interface
MenuAvsSynchError: AVS Problem Overview
MenuLdap: LDAP Interface
MenuApc: Printing
MenuApc: Print
MenuPrintSend: Send Letter
MenuPrintDownload: Download Letter
MenuPrintLog: LPR Interface
MenuPrintAck: Acknowledge Printing
MenuCommCenter: Notifications
MenuMailCenter: Email
MenuMailHtml: Html
MenuMailPlain: Text
MenuMailAttachment: Attachment
MenuApiDocs: API documentation
MenuSwagger: OpenAPI 2.0 (Swagger)

View File

@ -12,8 +12,8 @@ NewsHeading: Aktuelles
InfoHeading: Informationen
LegalHeading: Rechtliche Informationen
VersionHeading: Versionsgeschichte
SystemMessageHeading: Uni2work Statusmeldung
SystemMessageListHeading: Uni2work Statusmeldungen
SystemMessageHeading: FRADrive Statusmeldung
SystemMessageListHeading: FRADrive Statusmeldungen
HeadingHelpRequest: Supportanfrage/Verbesserungsvorschlag
ProfileHeading: Benutzereinstellungen
ProfileDataHeading: Gespeicherte Benutzerdaten

View File

@ -12,8 +12,8 @@ NewsHeading: News
InfoHeading: Information
LegalHeading: Legal
VersionHeading: Version history
SystemMessageHeading: Uni2work system message
SystemMessageListHeading: Uni2work system message
SystemMessageHeading: FRADrive system message
SystemMessageListHeading: FRADrive system messages
HeadingHelpRequest: Support request/Suggestion
ProfileHeading: Settings
ProfileDataHeading: Personal information
@ -29,8 +29,8 @@ HeadingTermEditTid tid: Edit year #{tid}
TermCourseListHeading tid: Courses #{tid}
TermSchoolCourseListHeading tid school: Courses #{tid}, #{school}
CourseListTitle: All courses
CourseNewHeading: Create new course type
CourseEditHeading tid ssh csh: Edit course type #{tid}-#{ssh}-#{csh}
CourseNewHeading: Create new course category
CourseEditHeading tid ssh csh: Edit course category #{tid}-#{ssh}-#{csh}
SubmissionsCourse tid ssh csh: All submissions for Course #{tid}-#{ssh}-#{csh}
SubmissionsSheet sheetName: Submissions for #{sheetName}
SheetList tid ssh csh : #{tid}-#{ssh}-#{csh} Sheet Overview
@ -38,7 +38,7 @@ SheetNewHeading tid ssh csh : #{tid}-#{ssh}-#{csh} New Exercise Sheet
SheetTitle tid@TermId ssh@SchoolId csh@CourseShorthand sheetName@SheetName: #{tid}-#{ssh}-#{csh} #{sheetName}
SheetTitleNew tid@TermId ssh@SchoolId csh@CourseShorthand : #{tid}-#{ssh}-#{csh}: New sheet
SheetEditHead tid ssh csh sheetName: #{tid}-#{ssh}-#{csh} Edit #{sheetName}
SheetDelHead tid ssh csh sheetName: Do you really want to delete sheet #{sheetName} from course type #{tid}-#{ssh}-#{csh}? Any associated submissions and corrections will be lost!
SheetDelHead tid ssh csh sheetName: Do you really want to delete sheet #{sheetName} from course category #{tid}-#{ssh}-#{csh}? Any associated submissions and corrections will be lost!
SubmissionEditHead tid ssh csh sheetName: #{tid}-#{ssh}-#{csh} #{sheetName}: Edit/Create submission
CorrectionHead tid ssh csh sheetName cid: #{tid}-#{ssh}-#{csh} #{sheetName}: Marking
CorrectionsTitle: Assigned corrections
@ -48,8 +48,8 @@ CorrGrade: Mark submissions
TableHeadingCsvImport: CSV import
TableHeadingCsvExport: CSV export
FavouritesEmptyTip: Your courses and recently visited courses are shown here.
FavouritesToggleTip: The display mode for the current course type can be changed between automatic, permanent and never with a click on the star symbol.
FavouritesUnavailableTip: Quick Actions for this course type are currently not available.
FavouritesToggleTip: The display mode for the current course category can be changed between automatic, permanent and never with a click on the star symbol.
FavouritesUnavailableTip: Quick Actions for this course category are currently not available.
NavigationFavourites: Favourites
ErrorResponseTitleInternalError internalError: An internal error occurred
ErrorResponseTitleInvalidArgs invalidArgs: Request contained invalid arguments

View File

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2022 Gregor Kleen <gregor.kleen@ifi.lmu.de>,Sarah Vaupel <sarah.vaupel@ifi.lmu.de>,Steffen Jost <jost@tcs.ifi.lmu.de>,Winnie Ros <winnie.ros@campus.lmu.de>
# SPDX-FileCopyrightText: 2022-24 Gregor Kleen <gregor.kleen@ifi.lmu.de>,Sarah Vaupel <sarah.vaupel@ifi.lmu.de>,Steffen Jost <jost@tcs.ifi.lmu.de>,Winnie Ros <winnie.ros@campus.lmu.de>, Steffen Jost <s.jost@fraport.de>
#
# SPDX-License-Identifier: AGPL-3.0-or-later
@ -47,12 +47,12 @@ TablePassed: Bestanden
TableNotPassed: Nicht bestanden
TableTutorialTutors: Ausbilder
TableTutorialName: Bezeichnung
TableTutorialType: Art
TableTutorialRoom: Regulärer Raum
TableTutorialType: Typ
TableTutorialRoom: Raum
TableTutorialRoomHidden: Raum nur für Teilnehmer
TableTutorialRoomIsUnset !ident-ok: —
TableTutorialRoomIsHidden: Raum wird nur Teilnehmern angezeigt
TableTutorialTime: Zeit
TableTutorialOccurrence: Termin
TableTutorialDeregisterUntil: Abmeldungen bis
TableTutorialFirstDay: Starttag
TableActionsHead: Aktionen
@ -73,15 +73,22 @@ TableDiffDaysTooltip: Zeitspanne nach ISO 8601. Beispiel: "P2Y3M4D" ist eine Zei
TableExamOfficeLabel: Label-Name
TableExamOfficeLabelStatus: Label-Farbe
TableExamOfficeLabelPriority: Label-Priorität
TableQualification: Qualifikation
TableQualifications: Qualifikationen
TableCompany: Firma
TableCompanyFilter: Firma oder Nummer
TableCompanyShort: Firmenkürzel
TableCompanies: Firmen
TablePrimeCompany: Primäre Firma
TablePrimeCompanyShort: Kürzel primäre Firma
TableBookingCompany: Buchende Firma
TableBookingCompanyShort: Kürzel buchende Firma
TableCompanyNo: Firmennummer
TableCompanyNos: Firmennummern
TableCompanyUser: Firmenangehöriger
TableCompanyNrUsers: Firmenangehörige
TableCompanyNrSecondaryUsers: Sekundäre Firmenangehörige
TableCompanyReason: Notiz
TableCompanyNrSupers: Ansprechpartner
TableCompanyNrEmpSupervised: Firmenangehörige mit Ansprechpartner
TableCompanyNrEmpRerouted: Firmenangehörige mit Umleitung
@ -91,8 +98,13 @@ TableCompanyNrSupersDefault: Standard Ansprechpartner
TableCompanyNrForeignSupers: Firmenfremde Ansprechpartner
TableCompanyNrRerouteDefault: Standard Umleitungen
TableCompanyNrRerouteActive: Aktive Umleitungen
TableRerouteActive: Umleitung
TableCompanyPostalPreference: Benachrichtigungspräferenz neue Firmenangehörige
TableCompanyPinPassword: Pin Passwort für PDF Anhänge
TableSupervisor: Ansprechpartner
TableSupervisorActive: Aktiver Ansprechpartner
TableSupervisee: Klient
TableReason: Begründung
TableCreationTime: Erstellungszeit
TableJob !ident-ok: Job
TableJobContent !ident-ok: Parameter
@ -100,10 +112,13 @@ TableJobLockTime: Bearbeitung seit
TableJobLockInstance: Bearbeiter
TableJobCreationInstance: Ersteller
ActJobDelete: Job entfernen
ActJobDeleteForce n@Int: Auch vor #{pluralDEnN n "Minute"} gesperrte Jobs entfernen
TableJobActDeleteFeedback n@Int m@Int: #{n}/#{m} Jobs entfernt
TableFilterComma: Es können mehrere alternative Suchkriterien mit Komma getrennt angegeben werden, wovon mindestens eines erfüllt werden muss.
TableFilterCommaPlus: Mehrere alternative Suchkriterien mit Komma trennen. Mindestens ein Suchkriterium muss erfüllt werden, zusätzlich zu allen Suchkriterien mit vorangestelltem Plus-Symbol.
TableFilterCommaPlusShort: Unterstützt mehrere Kriterien mit Komma-Plus, siehe oben.
TableFilterCommaName: Mehrere Namen mit Komma trennen.
TableFilterCommaNameNr: Mehrere Namen oder Nummern mit Komma trennen. Nummern werden nur exakt gesucht.
TableFilterCommaNameNr: Mehrere Namen oder exakte Nummern mit Komma trennen.
TableUserEdit: Benutzer bearbeiten
TableRows: Zeilen
TableRows: Zeilen
TableUserParkingToken day@Text: Parkmarke #{day}

View File

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2022 Sarah Vaupel <sarah.vaupel@ifi.lmu.de>,Steffen Jost <jost@tcs.ifi.lmu.de>,Winnie Ros <winnie.ros@campus.lmu.de>
# SPDX-FileCopyrightText: 2022-24 Sarah Vaupel <sarah.vaupel@ifi.lmu.de>,Steffen Jost <jost@tcs.ifi.lmu.de>,Winnie Ros <winnie.ros@campus.lmu.de>, Steffen Jost <s.jost@fraport.de>
#
# SPDX-License-Identifier: AGPL-3.0-or-later
@ -20,7 +20,7 @@ TableMatrikelNr: AVS person no
TableSex: Sex
TableBirthday: Birthday
TableSchool: Department
TableCourse: Course
TableCourse: Course category
TableCourseMembers: Participants
TableExamOccurrence: Occurrence/room
TableExamName: Name
@ -48,14 +48,14 @@ TableNotPassed: Failed
TableTutorialTutors: Instructors
TableTutorialName: Name
TableTutorialType: Type
TableTutorialRoom: Regular room
TableTutorialRoom: Room
TableTutorialRoomHidden: Room only for participants
TableTutorialRoomIsUnset: —
TableTutorialRoomIsHidden: Room is only displayed to participants
TableTutorialDeregisterUntil: Deregister until
TableTutorialFirstDay: Start date
TableActionsHead: Actions
TableTutorialTime: Time
TableTutorialOccurrence: Session
TableNoFilter: No restriction
TableUserMatriculation: AVS number
TableColumnStudyFeatures: Features of study
@ -73,15 +73,22 @@ TableDiffDaysTooltip: Duration given according to ISO 8601. Example: "P2Y3M4D" i
TableExamOfficeLabel: Label name
TableExamOfficeLabelStatus: Label colour
TableExamOfficeLabelPriority: Label priority
TableQualification: Qualification
TableQualifications: Qualifications
TableCompany: Company
TableCompanyFilter: Company/Nr
TableCompanyShort: Company shorthand
TableCompanies: Companies
TablePrimeCompany: Primary company
TablePrimeCompanyShort: Primary company shorthand
TableBookingCompany: Booking company
TableBookingCompanyShort: Booking company shorthand
TableCompanyNo: Company number
TableCompanyNos: Company numbers
TableCompanyUser: Associate
TableCompanyNrUsers: Associates
TableCompanyNrSecondaryUsers: Secondary Associates
TableCompanyReason: Note
TableCompanyNrSupers: Supervisors
TableCompanyNrEmpSupervised: Supervised employees
TableCompanyNrEmpRerouted: Employees having reroute
@ -91,8 +98,13 @@ TableCompanyNrSupersDefault: Default supervisors
TableCompanyNrForeignSupers: External Supervisors
TableCompanyNrRerouteDefault: Default reroutes
TableCompanyNrRerouteActive: Active reroutes
TableRerouteActive: Reroute
TableCompanyPostalPreference: Default notification preference
TableCompanyPinPassword: Pin password for PDF attachments
TableSupervisor: Supervisor
TableSupervisorActive: Active supervisor
TableSupervisee: Supervisee
TableReason: Reason
TableCreationTime: Creation
TableJob !ident-ok: Job
TableJobContent !ident-ok: Parameters
@ -100,10 +112,13 @@ TableJobLockTime: Lock time
TableJobLockInstance: Worker
TableJobCreationInstance: Creator
ActJobDelete: Delete job
ActJobDeleteForce n: Also delete jobs locked #{pluralENsN n "minute"} ago
TableJobActDeleteFeedback n@Int m@Int: #{n}/#{m} queued jobs deleted
TableFilterComma: Separate multiple alternative filter criteria by comma, at least one of which must be fulfilled.
TableFilterCommaPlus: Separate multiple alternative filter criteria by comma, at least one of which must be fulfilled in addition to all criteria preceded by a plus symbol.
TableFilterCommaPlusShort: Support multiple criteria with comma/plus, see above.
TableFilterCommaName: Separate names by comma.
TableFilterCommaNameNr: Separate names and numbers by comma. Numbers have to match exact.
TableFilterCommaNameNr: Separate names and exact numbers by comma.
TableUserEdit: Edit user
TableRows: Rows
TableRows: Rows
TableUserParkingToken day: Parking token #{day}

View File

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2023 Steffen Jost <jost@tcs.ifi.lmu.de>,Gregor Kleen <gregor.kleen@ifi.lmu.de>,Sarah Vaupel <sarah.vaupel@ifi.lmu.de>,Winnie Ros <winnie.ros@campus.lmu.de>
# SPDX-FileCopyrightText: 2023-25 Steffen Jost <jost@tcs.ifi.lmu.de>,Gregor Kleen <gregor.kleen@ifi.lmu.de>,Sarah Vaupel <sarah.vaupel@ifi.lmu.de>,Winnie Ros <winnie.ros@campus.lmu.de>,Steffen Jost <s.jost@fraport.de>
#
# SPDX-License-Identifier: AGPL-3.0-or-later
@ -25,6 +25,7 @@ RGTutorialParticipants tutn@TutorialName: Kursteilnehmer:innen (#{tutn})
RGExamRegistered examn@ExamName: Angemeldet zur Prüfung „#{examn}“
RGSheetSubmittor shn@SheetName: Abgebende für das Übungsblatt „#{shn}“
CommSubject: Betreff
CommContent: Inhalt
CommAttachments: Anhänge
CommAttachmentsTip: Im Allgemeinen ist es vorzuziehen Dateien, die Sie mit den Empfängern teilen möchten, als Material hochzuladen (und ggf. in der Nachricht zu verlinken). So ist die Datei für die Empfänger dauerhaft abrufbar und auch Personen, die sich z.B. erst später zur Kursart anmelden, haben Zugriff auf die Datei.
CommSuccess n@Int: Nachricht wurde an #{n} Empfänger versandt
@ -80,8 +81,10 @@ MultiUserFieldExplanationAnyUser: Dieses Eingabefeld sucht in den Adressen aller
MultiUserFieldInvitationExplanation: An Adressen, die so keinem Uni2work-Benutzer/keiner Uni2work-Benutzerin zugeordnet werden können, wird eine Einladung per E-Mail versandt.
MultiUserFieldInvitationExplanationAlways: Es wird an alle Adressen, die Sie hier angeben, eine Einladung per E-Mail versandt.
AmbiguousEmail: E-Mail-Adresse nicht eindeutig
UnknownEmail: E-Mail-Adresse konnte keinem bekannten Benutzer zugeordnet werden
InvalidEmailAddress: E-Mail-Adresse ist ungültig
InvalidEmailAddressWith e@Text: E-Mail-Adresse #{show e} ist ungültig
MailFileAttachment: Dateianhang
UtilExamResultGrade: Note
UtilExamResultPass: Bestanden/Nicht Bestanden
UtilExamResultNoShow: Nicht erschienen
@ -89,6 +92,7 @@ UtilExamResultVoided: Entwertet
CourseOption tid@TermId ssh@SchoolId csh@CourseShorthand coursen@CourseName !ident-ok: #{tid} - #{ssh} - #{csh}: #{coursen}
RoomReferenceNone !ident-ok: —
RoomReferenceSimple !ident-ok: Text
RoomReferenceSimpleAt r@Text: in Raum #{r}
RoomReferenceLink: Link & Anweisungen
RoomReferenceSimpleText: Raum
RoomReferenceSimpleTextPlaceholder: Raum
@ -96,9 +100,11 @@ RoomReferenceLinkLink !ident-ok: Link
RoomReferenceLinkLinkPlaceholder !ident-ok: URL
RoomReferenceLinkInstructions: Anweisungen
RoomReferenceLinkInstructionsPlaceholder: Anweisungen
UtilNoneSet: Keine angegeben
UtilEmptyChoice: Auswahl war leer
UtilEmptyNoChangeTip: Eine leere Eingabe belässt den vorherigen Wert unverändert.
MultiNoSelection: Keine Auswahl
MustBePositive: muss positiv sein
#invitation.hs
InvitationAction: Aktion

View File

@ -1,18 +1,18 @@
# SPDX-FileCopyrightText: 2023 Sarah Vaupel <sarah.vaupel@ifi.lmu.de>,Winnie Ros <winnie.ros@campus.lmu.de>,Steffen Jost <jost@tcs.ifi.lmu.de>
# SPDX-FileCopyrightText: 2023-25 Sarah Vaupel <sarah.vaupel@ifi.lmu.de>,Winnie Ros <winnie.ros@campus.lmu.de>,Steffen Jost <jost@tcs.ifi.lmu.de>,Steffen Jost <s.jost@fraport.de>
#
# SPDX-License-Identifier: AGPL-3.0-or-later
#communication.hs
RecipientCustom: Custom recipients
RGCourseParticipants: Course type participants
RGCourseParticipants: Course category participants
RGCourseLecturers: Course administrators
RGCourseCorrectors: Course type correctors
RGCourseCorrectors: Course category correctors
RGCourseTutors: Course instructors
RGCourseParticipantsInTutorial: Course type participants who are registered for at least one course
RGCourseParticipantsInTutorial: Course category participants who are registered for at least one course
RGCourseUnacceptedApplicants: Applicants not accepted
RecipientToggleAll: All/None
CommCourseTestSubject customSubject: [TEST] #{customSubject}
UtilCommCourseSubject: Course type message
UtilCommCourseSubject: Course category message
UtilCommFirmSubject: Company message
CommRecipients: Recipients
CommRecipientsTip: You always receive a copy of the message
@ -25,8 +25,9 @@ RGTutorialParticipants tutn: Course participants (#{tutn})
RGExamRegistered examn: Registered for exam “#{examn}”
RGSheetSubmittor shn: Submitted for exercise sheet “#{shn}”
CommSubject: Subject
CommContent: Content
CommAttachments: Attachments
CommAttachmentsTip: In general it is preferable to upload files as course type material instead of sending them as attachments. You can then link to the material from the message. The file is then permanently accessable to the recipients and to persons that, for example, register for the Course type at a later date.
CommAttachmentsTip: In general it is preferable to upload files as course category material instead of sending them as attachments. You can then link to the material from the message. The file is then permanently accessable to the recipients and to persons that, for example, register for the Course category at a later date.
CommSuccess n: Message was sent to #{n} #{pluralEN n "recipient" "recipients"}
CommTestSuccess: Message was sent only to yourself for testing purposes
@ -80,8 +81,10 @@ MultiUserFieldExplanationAnyUser: This input searches through the addresses of a
MultiUserFieldInvitationExplanation: For addresses, which are not found in this way, an invitation will be sent via email.
MultiUserFieldInvitationExplanationAlways: An invitation will be sent via email to all addresses you enter here.
AmbiguousEmail: Email address is ambiguous
UnknownEmail: Email adresse is not associated with any registred user
InvalidEmailAddress: Email address is invalid
InvalidEmailAddressWith e: Email asdress #{show e} is invalid
MailFileAttachment: Attached file
UtilExamResultGrade: Grade
UtilExamResultPass: Passed/Failed
UtilExamResultNoShow: Not present
@ -89,6 +92,7 @@ UtilExamResultVoided: Voided
CourseOption tid ssh csh coursen: #{tid} - #{ssh} - #{csh}: #{coursen}
RoomReferenceNone: —
RoomReferenceSimple: Text
RoomReferenceSimpleAt r: at room #{r}
RoomReferenceLink: Link & Instructions
RoomReferenceSimpleText: Room
RoomReferenceSimpleTextPlaceholder: Room
@ -96,9 +100,11 @@ RoomReferenceLinkLink: Link
RoomReferenceLinkLinkPlaceholder: URL
RoomReferenceLinkInstructions: Instructions
RoomReferenceLinkInstructionsPlaceholder: Instructions
UtilNoneSet: None set
UtilEmptyChoice: Empty selection
UtilEmptyNoChangeTip: Existing values remain unchanged if this field is left empty.
MultiNoSelection: No selection
MustBePositive: must be positive
#invitation.hs
InvitationAction: Action

View File

@ -1,4 +1,4 @@
-- SPDX-FileCopyrightText: 2022-23 Gregor Kleen <gregor.kleen@ifi.lmu.de>,Steffen Jost <s.jost@fraport.de>
-- SPDX-FileCopyrightText: 2022-24 Gregor Kleen <gregor.kleen@ifi.lmu.de>,Steffen Jost <s.jost@fraport.de>
--
-- SPDX-License-Identifier: AGPL-3.0-or-later
@ -8,7 +8,7 @@ TransactionLog
instance InstanceId
initiator UserId Maybe -- User associated with performing this action
remote IP Maybe -- Remote party that triggered this action via HTTP
info Value -- JSON-encoded `Transaction`
info Value -- JSON-encoded `Transaction`. Value allows full backwards compatibility
deriving Eq Read Show Generic
InterfaceLog
@ -26,6 +26,13 @@ InterfaceHealth
interface Text
subtype Text Maybe
write Bool Maybe
hours Int
hours Int -- negative number: never expires, i.e. if the last entry is a success, this remains indefinitely
UniqueInterfaceHealth interface subtype write !force -- Note that nullable fields must be either empty or unique
deriving Eq Read Show Generic
ProblemLog
time UTCTime default=now()
info Value -- generic JSON Value allows maximum backwards compatibility
solved UTCTime Maybe
solver UserId Maybe -- User who marked this problem as done
deriving Eq Read Show Generic

View File

@ -1,4 +1,4 @@
-- SPDX-FileCopyrightText: 2022 Steffen Jost <jost@tcs.ifi.lmu.de>
-- SPDX-FileCopyrightText: 2022-24 Steffen Jost <jost@tcs.ifi.lmu.de>
--
-- SPDX-License-Identifier: AGPL-3.0-or-later
@ -16,27 +16,19 @@
UserAvs
personId AvsPersonId -- unique identifier for user throughout avs; newtype for Int
user UserId
noPerson Int default=0 -- only needed for manual communication with personnel from Ausweisverwaltungsstelle
noPerson Int default=0 -- only needed for manual communication with personnel from Ausweisverwaltungsstelle, redundant since needed for filtering
lastSynch UTCTime default=now()
lastSynchError Text Maybe
lastPersonInfo AvsPersonInfo Maybe -- just to discern field changes
lastFirmInfo AvsFirmInfo Maybe -- just to discern field changes
lastCardNo AvsFullCardNo Maybe -- just to discern changes
UniqueUserAvsUser user
UniqueUserAvsId personId
deriving Generic Show
-- Multiple UserAvsCards per UserAvs is possible and not too uncommon.
-- Purpose of saving cards is to detect external changes in qualifications and postal addresses
-- TODO: This table will be deleted if AVS CR3 SCF-165 is implemented
UserAvsCard
personId AvsPersonId
cardNo AvsFullCardNo
card AvsDataPersonCard
lastSynch UTCTime
-- UniqueAvsCard cardNo -- Note: cardNo is not unique; invalid cardNo may be reissued to different persons
deriving Generic
AvsSync
user UserId -- Note: we need to lookup UserAvs Entity anyway, so no benefit from storing AvsPersonId here
creationTime UTCTime
pause Day Maybe
pause Day Maybe -- Don't synch if last synch after this day, otherwise synch
UniqueAvsSyncUser user
deriving Generic
deriving Generic Show

View File

@ -1,25 +1,20 @@
-- SPDX-FileCopyrightText: 2022 Sarah Vaupel <sarah.vaupel@ifi.lmu.de>,Steffen Jost <jost@tcs.ifi.lmu.de>
-- SPDX-FileCopyrightText: 2022-25 Sarah Vaupel <sarah.vaupel@ifi.lmu.de>,Steffen Jost <s.jost@fraport.de>
--
-- SPDX-License-Identifier: AGPL-3.0-or-later
-- Description of companies associated with users
Company
name CompanyName -- == (CI Text)
shorthand CompanyShorthand -- == (CI Text) and CompanyKey :: CompanyShorthand -> CompanyId FUTURE TODO: a shorthand will become available through the AVS interface in the future
avsId Int default=0 -- primary key from avs
prefersPostal Bool default=false -- new company users prefers letters by post instead of email
postAddress StoredMarkup Maybe -- default company postal address
email UserEmail Maybe -- Case-insensitive generic company eMail address
UniqueCompanyName name
UniqueCompanyShorthand shorthand
-- UniqueCompanyAvsId avsId -- should be the case, unclear if enforcing works here, since we cannot query avs by company id
Primary shorthand -- newtype Key Company = CompanyKey { unCompanyKey :: CompanyShorthand }
name CompanyName -- == (CI Text) -- NOTE: Fraport department name may carry additional information; use the Shorthand with respect to UserCompanyDepartment
shorthand CompanyShorthand -- == (CI Text) and CompanyKey :: CompanyShorthand -> CompanyId A change to AvsId as primary key is too much work and not strictly necessary due to Uniqueness
avsId Int default=0 -- primary key from avs, use negative numbers for non-AVS companies
prefersPostal Bool default=true -- new company users prefers letters by post instead of email
postAddress StoredMarkup Maybe -- default company postal address, including company name
email UserEmail Maybe -- Case-insensitive generic company eMail address
pinPassword Bool default=true -- new company users only: should sensitive PDF email attachement be protected by a password?
-- UniqueCompanyName name -- Should be Unique in AVS, but we do not yet need to enforce it
-- UniqueCompanyShorthand shorthand -- unnecessary, since it is the primary key already
UniqueCompanyAvsId avsId -- Should be the key, is not for historical reasons and for convenience in URLs and columns
Primary shorthand -- newtype Key Company = CompanyKey { unCompanyKey :: CompanyShorthand }
deriving Ord Eq Show Generic Binary
-- TODO: a way to populate this table (manually)
CompanySynonym
synonym CompanyName
canonical CompanyShorthand OnDeleteCascade OnUpdateCascade
UniqueCompanySynonym synonym
deriving Ord Eq Show Generic

View File

@ -28,13 +28,12 @@ Course -- Information about a single course; contained info is always visible
TermSchoolCourseName term school name -- name must be unique within school and semester
deriving Generic
CourseEvent
type (CI Text)
course CourseId OnDeleteCascade OnUpdateCascade
room RoomReference Maybe
roomHidden Bool default=false
time Occurrences
note StoredMarkup Maybe
lastChanged UTCTime default=now()
type (CI Text)
course CourseId OnDeleteCascade OnUpdateCascade
roomHidden Bool default=false
time (JSONB Occurrences)
note StoredMarkup Maybe
lastChanged UTCTime default=now()
deriving Generic
CourseAppInstructionFile

View File

@ -37,16 +37,17 @@ ExamPart
UniqueExamPartName exam name !force
deriving Read Show Eq Ord Generic
ExamOccurrence
exam ExamId
name ExamOccurrenceName
room RoomReference Maybe
roomHidden Bool default=false
capacity Word64 Maybe
start UTCTime
end UTCTime Maybe
description StoredMarkup Maybe
exam ExamId
name ExamOccurrenceName
examiner UserId Maybe
room RoomReference Maybe
roomHidden Bool default=false
capacity Word64 Maybe
start UTCTime
end UTCTime Maybe
description StoredMarkup Maybe
UniqueExamOccurrence exam name
deriving Generic
deriving Eq Ord Show Generic Binary
ExamRegistration
exam ExamId
user UserId

View File

@ -20,11 +20,11 @@ CronLastExec
time UTCTime -- When was the job executed
instance InstanceId -- Which uni2work-instance did the work
UniqueCronLastExec job
deriving Generic
deriving Generic Show
TokenBucket
ident TokenBucketIdent
lastValue Int64
lastAccess UTCTime
Primary ident
deriving Generic
deriving Generic Show

View File

@ -1,28 +1,30 @@
-- SPDX-FileCopyrightText: 2022-23 Sarah Vaupel <sarah.vaupel@ifi.lmu.de>,Steffen Jost <jost@tcs.ifi.lmu.de>
-- SPDX-FileCopyrightText: 2022-25 Sarah Vaupel <sarah.vaupel@ifi.lmu.de>,Steffen Jost <s.jost@fraport.de>
--
-- SPDX-License-Identifier: AGPL-3.0-or-later
Qualification
-- INVARIANT: 2*refreshWithin < validDuration
school SchoolId --TODO: Ansprechpartner der Schule in Briefe erwähnen
shorthand (CI Text)
name (CI Text)
description StoredMarkup Maybe -- user-defined large Html, ought to contain full description
validDuration Int Maybe -- > 0, qualification is valid indefinitely or for a specified number of months, use with addMonthsDay
auditDuration Int Maybe -- > 0, number of months to keep audit log and LmsUserIdents; or indefinitely (dangerous, since LmsIdents may run out)
refreshWithin CalendarDiffDays Maybe -- notify users about renewal within this number of month/days before expiry; to be used with addGregorianDurationClip
refreshReminder CalendarDiffDays Maybe -- send a second notification about renewal within this number of month/days before expiry
elearningStart Bool -- automatically schedule e-refresher
-- elearningOnly Bool -- successful E-learing automatically increases validity. NO!
expiryNotification Bool default=true -- should expiryNotification be generated for this qualification?
avsLicence AvsLicence Maybe -- if set, valid QualificationUsers are synchronized to AVS as a driving licence
sapId Text Maybe -- if set, valid QualificationUsers with userCompanyPersonalNumber are transmitted via SAP interface under this id
school SchoolId -- 1
shorthand (CI Text) -- 2
name (CI Text) -- 3
description StoredMarkup Maybe -- 4 user-defined large Html, ought to contain full description
validDuration Int Maybe -- 5 if > 0, qualification is valid indefinitely or for a specified number of months, use with addMonthsDay
auditDuration Int default=366 -- 6 number of days to keep LMS audit log and LmsUserIdents -- TODO: audit period for QualificationUser/Block as well
refreshWithin CalendarDiffDays Maybe -- 7 notify users about renewal within this number of month/days before expiry; to be used with addGregorianDurationClip
refreshReminder CalendarDiffDays Maybe -- 8 send a second notification about renewal within this number of month/days before expiry
elearningStart Bool -- 9 automatically schedule e-refresher
elearningRenews Bool default=true -- 10 successful e-learing automatically increases validity automatically by validDuration
elearningLimit Int Maybe -- 11 limit of e-learning attempts, currently only for informative purposes, as it is enforced by LMS only
lmsReuses QualificationId Maybe -- 12 if set, lms is also included within the given qualification's lms, but only for direct routes. AuditDuration is used from this Qualification instead.
expiryNotification Bool default=true -- 13 should expiryNotification be generated for this qualification?
avsLicence AvsLicence Maybe -- 14 if set, valid QualificationUsers are synchronized to AVS as a driving licence
sapId Text Maybe -- 15 if set, valid QualificationUsers with userCompanyPersonalNumber are transmitted via SAP interface under this id
SchoolQualificationShort school shorthand -- must be unique per school and shorthand
SchoolQualificationName school name -- must be unique per school and name
-- across all schools, only one qualification may be a driving licence:
UniqueQualificationAvsLicence avsLicence !force -- either empty or unique
-- across all schools, only one qualification may be a driving licence -- NO LONGER TRUE
-- UniqueQualificationAvsLicence avsLicence !force -- either empty or unique
-- NOTE: two NULL values are not equal for the purpose of Uniqueness constraints!
deriving Eq Generic
deriving Show Eq Generic Binary
-- TODOs:
-- - Enstehen Kosten, wenn Teilnehmer für KnowHow eingereiht werden, aber nicht am Kurs teilnehmen?
@ -40,19 +42,20 @@ Qualification
-- - PinReset==1 mit bestehendem Passwort kann problemlos erneut gesendet werden
-- - Flag "interner Mitarbeiter" wird von Know-How ignoriert / nicht ausgewertet (legacy)
QualificationPrecondition -- NOTE: this can only be enforced through a background job adding or removing qualifications
qualification QualificationId OnDeleteCascade OnUpdateCascade -- AND: not unique, ie. qualification can have multiple required preconditions
required [QualificationId] -- OR : alternatives, any one will suffice
continuous Bool -- expiring precondition blocks qualification
deriving Generic
-- QualificationPrecondition -- NOTE: this can only be enforced through a background job adding or removing qualifications
-- qualification QualificationId OnDeleteCascade OnUpdateCascade -- AND: not unique, ie. qualification can have multiple required preconditions
-- required [QualificationId] -- OR : alternatives, any one will suffice -- we don't want array, since we have recursive CTEs
-- continuous Bool -- expiring precondition blocks qualification
-- deriving Generic Show
-- Maybe an alternative for online qualification validity checking, transitivity through recursive CTEs? (already available in our version)
-- QualificationRequirement
-- qualification QualificationId OnDeleteCascade OnUpdateCascade
-- requirement QualificationId OnDeleteCascade OnUpdateCascade
-- group Text -- OR: several requirements within the same group are considered equivalent
-- UniqueQualificationRequirement qualification requirement
--
QualificationRequirement
qualification QualificationId OnDeleteCascade OnUpdateCascade
requirement QualificationId OnDeleteCascade OnUpdateCascade
group Int -- OR: several requirements within the same group are considered equivalent; no order between groups
note Text -- for humans only, no semantical effect
UniqueQualificationRequirement qualification requirement
deriving Generic Show
-- TODO: connect Qualification with Exams!
@ -60,7 +63,7 @@ QualificationEdit
user UserId
time UTCTime
qualification QualificationId OnDeleteCascade OnUpdateCascade
deriving Generic
deriving Generic Show
QualificationUser
user UserId OnDeleteCascade OnUpdateCascade
@ -69,11 +72,11 @@ QualificationUser
lastRefresh Day -- lastRefresh > validUntil possible, if Qualification^elearningOnly == False
firstHeld Day -- first time the qualification was earned, should never change
scheduleRenewal Bool default=true -- if false, no automatic renewal is scheduled and the qualification expires
lastNotified UTCTime default=now() -- last notficiation about being invalid
lastNotified UTCTime default=now() -- last notficiation about actual licence validity changes (does not entail e-learning notifications)
-- Reasons and temporary revocations are implemented through QualificationUserBlock
-- TODO: adjust SAP interface to transmit end dates
UniqueQualificationUser qualification user
deriving Generic
deriving Generic Show
QualificationUserBlock
qualificationUser QualificationUserId OnDeleteCascade OnUpdateCascade
@ -130,7 +133,7 @@ LmsUser
-- Primary ident -- newtype Key LmsUserId = LmsUserKey { unLmsUser :: Text } -- change LmsIdent -> Text. Do we want this? No.
UniqueLmsIdent ident -- idents must be unique accross all qualifications, since idents are global within LMS!
UniqueLmsQualificationUser qualification user -- each user may be enrolled at most once per course
deriving Generic
deriving Generic Show
-- LmsUserStatus
-- lmsUser LmsUserId OnDeleteCascade OnUpdateCascade
@ -148,7 +151,7 @@ LmsReport
lock Bool -- (0|1)
timestamp UTCTime default=now()
UniqueLmsReport qualification ident -- required by DBTable
deriving Generic
deriving Generic Show
-- LmsAudit removed by commit 71cde92a
-- due to frequent transmit errors, a separate lms tranmission log is necessary again
@ -160,4 +163,16 @@ LmsReportLog
lock Bool -- (0|1)
timestamp UTCTime default=now()
missing Bool default=false
deriving Generic
deriving Generic Show
-- Table to manage unknown or orphaned lms identifiers
LmsOrphan
qualification QualificationId OnDeleteCascade OnUpdateCascade
ident LmsIdent -- must be unique accross all LMS courses!
seenFirst UTCTime default=now() -- first time reported by LMS
seenLast UTCTime default=now() -- last acknowledgement by LMS, deletion uses QualificationAuditDuration
deletedLast UTCTime Maybe -- last deletion request sent to LMS
resultLast LmsState -- last received learning state
reason Text Maybe -- to mark explicit e-learning deletions, etc
UniqueLmsOrphan qualification ident -- unlike other tables, LMS Idents must only be unique within qualification, allowing orphans to be handled independently
deriving Generic Show

View File

@ -10,22 +10,23 @@ PrintJob
created UTCTime
acknowledged UTCTime Maybe
recipient UserId Maybe OnDeleteSetNull OnUpdateCascade -- optional as some letters may contain just an address
affected UserId Maybe OnDeleteSetNull OnUpdateCascade -- subject of the letter
sender UserId Maybe OnDeleteSetNull OnUpdateCascade -- senders and associations are optional
course CourseId Maybe OnDeleteCascade OnUpdateCascade
qualification QualificationId Maybe OnDeleteCascade OnUpdateCascade
lmsUser LmsIdent Maybe OnDeleteSetNull OnUpdateCascade -- allows tracking if recipient has been notified; must be unique
-- UniquePrintJobLmsUser lmsUser -- Note that in fact multiple print jobs per LMS user are possible!
-- UniquePrintJobApcIdent apcIdent -- TODO: not yet enforced, since LmsIdent is currently used
deriving Generic
deriving Generic Show
PrintAcknowledge -- just to store acknowledging requests to be evaluated by a background job later on
apcIdent Text
timestamp UTCTime default=now()
processed Bool
deriving Generic
deriving Generic Show
PrintAckIdAlias
needle Text
replacement Text
priority Int
deriving Generic
deriving Generic Show

View File

@ -6,10 +6,9 @@ Tutorial json
name TutorialName
course CourseId OnDeleteCascade OnUpdateCascade
type (CI Text) -- "Tutorium", "Zentralübung", ...
capacity Int Maybe -- limit for enrolment in this tutorial
room RoomReference Maybe
capacity Int Maybe -- limit for enrolment in this tutorial
roomHidden Bool default=false
time Occurrences
time (JSONB Occurrences)
regGroup (CI Text) Maybe -- each participant may register for one tutorial per regGroup
registerFrom UTCTime Maybe
registerTo UTCTime Maybe
@ -25,8 +24,19 @@ Tutor
UniqueTutor tutorial user
deriving Generic
TutorialParticipant
tutorial TutorialId OnDeleteCascade OnUpdateCascade
user UserId
tutorial TutorialId OnDeleteCascade OnUpdateCascade
user UserId
company CompanyId Maybe
drivingPermit UserDrivingPermit Maybe
eyeExam UserEyeExam Maybe
note Text Maybe
UniqueTutorialParticipant tutorial user
deriving Eq Ord Show
deriving Generic
deriving Eq Ord Show Generic
TutorialParticipantDay
tutorial TutorialId OnDeleteCascade OnUpdateCascade
user UserId OnDeleteCascade OnUpdateCascade
day Day
attendance Bool default=true
note Text Maybe
UniqueTutorialParticipantDay tutorial user day
deriving Show Generic

View File

@ -1,4 +1,4 @@
-- SPDX-FileCopyrightText: 2022 Gregor Kleen <gregor.kleen@ifi.lmu.de>,Sarah Vaupel <sarah.vaupel@ifi.lmu.de>,Steffen Jost <jost@cip.ifi.lmu.de>,Steffen Jost <jost@tcs.ifi.lmu.de>
-- SPDX-FileCopyrightText: 2022-24 Gregor Kleen <gregor.kleen@ifi.lmu.de>,Sarah Vaupel <sarah.vaupel@ifi.lmu.de>,Steffen Jost <jost@tcs.ifi.lmu.de>,Steffen Jost <s.jost@fraport.de>
--
-- SPDX-License-Identifier: AGPL-3.0-or-later
@ -14,14 +14,14 @@
User json -- Each Uni2work user has a corresponding row in this table; created upon first login.
surname UserSurname -- Display user names always through 'nameWidget displayName surname'
displayName UserDisplayName
displayEmail UserEmail
email UserEmail -- Case-insensitive eMail address, used for sending TODO: make this nullable
ident UserIdent -- Case-insensitive user-identifier
displayEmail UserEmail -- Case-insensitive eMail address, used for sending; leave empty for using auto-update CompanyEmail via UserCompany
email UserEmail -- Case-insensitive eMail address, used for identification and fallback for sending. Defaults to "AVSNO:dddddddd" if unknown
ident UserIdent -- Case-insensitive user-identifier. Defaults to "AVSID:dddddddd" if unknown
authentication AuthenticationMode -- 'AuthLDAP' or ('AuthPWHash'+password-hash)
lastAuthentication UTCTime Maybe -- last login date
created UTCTime default=now()
lastLdapSynchronisation UTCTime Maybe
ldapPrimaryKey UserEduPersonPrincipalName Maybe
ldapPrimaryKey UserEduPersonPrincipalName Maybe -- Fraport Personnel Number or Email-Prefix for @fraport.de work here
tokensIssuedAfter UTCTime Maybe -- do not accept bearer tokens issued before this time (accept all tokens if null)
matrikelnummer UserMatriculation Maybe -- usually a number; AVS Personalnummer; nicht Fraport Personalnummer!
firstName Text -- For export in tables, pre-split firstName from displayName
@ -44,9 +44,9 @@ User json -- Each Uni2work user has a corresponding row in this table; create
mobile Text Maybe
companyPersonalNumber Text Maybe -- Company will become a new table, but if company=fraport, some information is received via LDAP
companyDepartment Text Maybe -- thus we store such information for ease of reference directly, if available
pinPassword Text Maybe -- used to encrypt pins within emails
postAddress StoredMarkup Maybe
postLastUpdate UTCTime Maybe -- record postal address updates
pinPassword Text Maybe -- used to encrypt pins within emails, defaults to cardno.version
postAddress StoredMarkup Maybe -- including company name, if any, but excluding username; leave empty for using auto-update CompanyPostAddress via UserCompany
postLastUpdate UTCTime Maybe -- record postal address updates
prefersPostal Bool default=false -- user prefers letters by post instead of email
examOfficeGetSynced Bool default=true -- whether synced status should be displayed for exam results by default
examOfficeGetLabels Bool default=true -- whether labels should be displayed for exam results by default
@ -61,42 +61,52 @@ UserFunction -- Administratively assigned functions (lecturer, admin, evaluation
function SchoolFunction
UniqueUserFunction user school function
deriving Generic
UserSystemFunction
UserSystemFunction Show
user UserId
function SystemFunction -- Defined in Model.Types.User
manual Bool -- Inserted manually by Admin or automatic from LDAP
isOptOut Bool -- User has currently deactivate the role for themselves
UniqueUserSystemFunction user function
deriving Generic
deriving Generic Show
UserExamOffice
user UserId
field StudyTermsId
UniqueUserExamOffice user field
deriving Generic
deriving Generic Show
UserSchool -- Managed by users themselves, encodes "schools of interest"
user UserId
school SchoolId
isOptOut Bool -- true if this a marker, that the user manually deleted this entry; it should not be recreated automatically
UniqueUserSchool user school
deriving Generic
deriving Generic Show
UserGroupMember
group UserGroupName
user UserId
primary Checkmark nullable
UniquePrimaryUserGroupMember group primary !force
UniqueUserGroupMember group user
deriving Generic
deriving Generic Show
UserCompany
user UserId
company CompanyId OnDeleteCascade OnUpdateCascade
supervisor Bool default=false -- should this user be made supervisor for all _new_ users associated with this company?
supervisorReroute Bool default=false -- if supervisor is true, should this supervisor receive email for _new_ company users?
priority Int default=0 -- higher number, higher priority; default=1 for Haskell-Code
useCompanyAddress Bool default=true -- if true, CompanyPostalAddress and CompanyEmail are used if UserPostalAddress/UserDisplayEmail are Nothing, respects priority
reason Text Maybe -- miscellaneous note, e.g. Superior
UniqueUserCompany user company -- a user may belong to multiple companies, but to each one only once
deriving Generic
deriving Generic Show
UserSupervisor
supervisor UserId -- multiple supervisor per trainee possible
supervisor UserId -- multiple supervisor per trainee possible
user UserId
rerouteNotifications Bool -- User can be his own supervisor to receive notifications as well
UniqueUserSupervisor supervisor user -- each supervisor/user combination is unique (same supervisor can superviser the same user only once)
deriving Generic
rerouteNotifications Bool -- User can be his own supervisor to receive notifications as well
company CompanyId Maybe OnDeleteCascade OnUpdateCascade -- this supervisor was company default supervisor at time of entry
reason Text Maybe -- miscellaneous reason, e.g. Winterservice supervisision
UniqueUserSupervisor supervisor user -- each supervisor/user combination is unique (same supervisor can superviser the same user only once)
deriving Generic Show
UserDay
user UserId OnDeleteCascade OnUpdateCascade
day Day
parkingToken Bool default=false
UniqueUserDay user day
deriving Generic Show

65
package-lock.json generated
View File

@ -1,12 +1,12 @@
{
"name": "fradrive",
"version": "27.4.59",
"version": "27.5.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "fradrive",
"version": "27.4.59",
"version": "27.5.1",
"license": "AGPL-3.0-or-later",
"dependencies": {
"@babel/runtime": "^7.25.6",
@ -68,7 +68,6 @@
"karma-browserify": "^8.1.0",
"karma-chrome-launcher": "^3.2.0",
"karma-cli": "^2.0.0",
"karma-esbuild": "^2.3.0",
"karma-jasmine": "^5.1.0",
"karma-jasmine-html-reporter": "^2.1.0",
"karma-mocha-reporter": "^2.2.5",
@ -5815,9 +5814,9 @@
"license": "MIT"
},
"node_modules/cookie": {
"version": "0.7.2",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
"integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
"version": "0.4.2",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz",
"integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==",
"dev": true,
"license": "MIT",
"engines": {
@ -5983,9 +5982,9 @@
}
},
"node_modules/cross-spawn": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
"integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -6879,9 +6878,9 @@
"license": "ISC"
},
"node_modules/elliptic": {
"version": "6.6.1",
"resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.1.tgz",
"integrity": "sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==",
"version": "6.5.7",
"resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.7.tgz",
"integrity": "sha512-ESVCtTwiA+XhY3wyh24QqRGBoP3rEdDUl3EDUUo9tft074fi19IrdpH7hLCMMP3CIj7jb3W96rn8lt/BqIlt5Q==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -6939,9 +6938,9 @@
}
},
"node_modules/engine.io": {
"version": "6.6.2",
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.2.tgz",
"integrity": "sha512-gmNvsYi9C8iErnZdVcJnvCpSKbWTt1E8+JZo8b+daLninywUWi5NQ5STSHZ9rFjFO7imNcvb8Pc5pe/wMR5xEw==",
"version": "6.5.5",
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.5.tgz",
"integrity": "sha512-C5Pn8Wk+1vKBoHghJODM63yk8MvrO9EWZUfkAt5HAqIgPE4/8FF0PEGHXtEd40l223+cE5ABWuPzm38PHFXfMA==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -6950,7 +6949,7 @@
"@types/node": ">=10.0.0",
"accepts": "~1.3.4",
"base64id": "2.0.0",
"cookie": "~0.7.2",
"cookie": "~0.4.1",
"cors": "~2.8.5",
"debug": "~4.3.1",
"engine.io-parser": "~5.2.1",
@ -10114,20 +10113,6 @@
"node": ">= 6"
}
},
"node_modules/karma-esbuild": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/karma-esbuild/-/karma-esbuild-2.3.0.tgz",
"integrity": "sha512-iW3DjSGohEEkufSDmXRPZP7CNP0ye+Xt8fBCcenLqPL2u8+VHZYwlzwYyfs60vjhdf1i04xekhzI7gu8as1CLg==",
"dev": true,
"license": "MIT",
"dependencies": {
"chokidar": "^3.5.1",
"source-map": "0.6.1"
},
"peerDependencies": {
"esbuild": ">=0.17.0"
}
},
"node_modules/karma-jasmine": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-5.1.0.tgz",
@ -10940,9 +10925,9 @@
"license": "MIT"
},
"node_modules/nanoid": {
"version": "3.3.8",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz",
"integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==",
"version": "3.3.7",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
"integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
"dev": true,
"funding": [
{
@ -11226,9 +11211,9 @@
}
},
"node_modules/npm-run-all/node_modules/cross-spawn": {
"version": "6.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.6.tgz",
"integrity": "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==",
"version": "6.0.5",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
"integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -16946,9 +16931,9 @@
}
},
"node_modules/socket.io": {
"version": "4.8.1",
"resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.1.tgz",
"integrity": "sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg==",
"version": "4.7.5",
"resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.5.tgz",
"integrity": "sha512-DmeAkF6cwM9jSfmp6Dr/5/mfMwb5Z5qRrSXLpo3Fq5SqyU8CMF15jIN4ZhfSwu35ksM1qmHZDQ/DK5XTccSTvA==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -16956,7 +16941,7 @@
"base64id": "~2.0.0",
"cors": "~2.8.5",
"debug": "~4.3.2",
"engine.io": "~6.6.0",
"engine.io": "~6.5.2",
"socket.io-adapter": "~2.5.2",
"socket.io-parser": "~4.2.4"
},

View File

@ -1,6 +1,6 @@
{
"name": "fradrive",
"version": "27.4.59",
"version": "27.5.1",
"description": "",
"keywords": [],
"author": "",
@ -54,7 +54,6 @@
"karma-browserify": "^8.1.0",
"karma-chrome-launcher": "^3.2.0",
"karma-cli": "^2.0.0",
"karma-esbuild": "^2.3.0",
"karma-jasmine": "^5.1.0",
"karma-jasmine-html-reporter": "^2.1.0",
"karma-mocha-reporter": "^2.2.5",
@ -90,9 +89,6 @@
},
"scripts": {
"build": "node esbuild.config.mjs",
"start": "node esbuild.config.mjs --watch",
"lint": "eslint --config eslint.config.mjs --color frontend/src",
"lintfix": "eslint --config eslint.config.mjs --color --fix frontend/src",
"test": "echo \"karma-testsuite currently disabled, reporting success\""
"start": "node esbuild.config.mjs --watch"
}
}

View File

@ -3,7 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
name: uniworx
version: 27.4.59
version: 27.5.1
dependencies:
- base
- yesod

41
routes
View File

@ -1,4 +1,4 @@
-- SPDX-FileCopyrightText: 2022-2024 Sarah Vaupel <sarah.vaupel@uniworx.de>, Gregor Kleen <gregor.kleen@ifi.lmu.de>, Sarah Vaupel <sarah.vaupel@ifi.lmu.de>, Steffen Jost <jost@tcs.ifi.lmu.de>, Wolfgang Witt <Wolfgang.Witt@campus.lmu.de>
-- SPDX-FileCopyrightText: 2022-2025 Sarah Vaupel <sarah.vaupel@uniworx.de>, Gregor Kleen <gregor.kleen@ifi.lmu.de>, Sarah Vaupel <sarah.vaupel@ifi.lmu.de>, Steffen Jost <jost@tcs.ifi.lmu.de>, Wolfgang Witt <Wolfgang.Witt@campus.lmu.de>, Steffen Jost <s.jost@fraport.de>
--
-- SPDX-License-Identifier: AGPL-3.0-or-later
@ -53,11 +53,12 @@
/ NewsR GET !free
/users UsersR GET POST -- no tags, i.e. admins only
/users/#CryptoUUIDUser AdminUserR GET POST
/users/#CryptoUUIDUser/delete AdminUserDeleteR POST
/users/#CryptoUUIDUser/hijack AdminHijackUserR GET POST !adminANDno-escalation
/users/#CryptoUUIDUser AdminUserR GET POST
/users/#CryptoUUIDUser/delete AdminUserDeleteR POST
/users/#CryptoUUIDUser/hijack AdminHijackUserR GET POST !adminANDno-escalation
/users/#CryptoUUIDUser/notifications UserNotificationR GET POST !self
/users/#CryptoUUIDUser/password UserPasswordR GET POST !selfANDis-pw-hash
/users/#CryptoUUIDUser/recipients UserRecipientsR GET !self
!/users/functionary-invite/new AdminNewFunctionaryInviteR GET POST
!/users/functionary-invite AdminFunctionaryInviteR GET POST
!/users/add AdminUserAddR GET POST
@ -69,14 +70,21 @@
/admin/crontab AdminCrontabR GET
/admin/crontab/jobs AdminJobsR GET POST
/admin/avs AdminAvsR GET POST
/admin/avs/#CryptoUUIDUser AdminAvsUserR GET
/admin/avs/#CryptoUUIDUser AdminAvsUserR GET POST
/admin/ldap AdminLdapR GET POST
/admin/problems AdminProblemsR GET
/admin/problems/no-contact ProblemUnreachableR GET
/admin/problems AdminProblemsR GET POST
/admin/problems/no-contact ProblemUnreachableR GET POST
/admin/problems/no-avs-id ProblemWithoutAvsId GET
/admin/problems/r-without-f ProblemFbutNoR GET
/admin/problems/avs ProblemAvsSynchR GET POST
/admin/problems/avs/errors ProblemAvsErrorR GET
/admin/config/interfaces ConfigInterfacesR GET POST
/comm CommCenterR GET
/comm/email MailCenterR GET POST
/comm/email/html/#CryptoUUIDSentMail MailHtmlR GET
/comm/email/plain/#CryptoUUIDSentMail MailPlainR GET
/comm/email/attachment/#CryptoUUIDSentMail/#Text MailAttachmentR GET
/print PrintCenterR GET POST !system-printer
/print/acknowledge/#Day/#Int/#Int PrintAckR GET POST !system-printer
@ -118,6 +126,7 @@
/firms FirmAllR GET POST -- not yet !supervisor
/firms/comm/+Companies FirmsCommR GET POST
/firms/supervision FirmsSupervisionR GET POST
/firm/#CompanyShorthand/comm FirmCommR GET POST
/firm/#CompanyShorthand FirmUsersR GET POST -- not yet !supervisor
/firm/#CompanyShorthand/supers FirmSupersR GET POST -- not yet !supervisor
@ -150,8 +159,9 @@
/school SchoolListR GET
!/school/new SchoolNewR GET POST
/school/#SchoolId SchoolR:
/ SchoolEditR GET POST
/edit SchoolEditR GET POST
/day/#Day SchoolDayR GET POST
/day/#Day/check SchoolDayCheckR GET
/participants ParticipantsListR GET !evaluation
/participants/#TermId/#SchoolId ParticipantsR GET !evaluation
@ -221,6 +231,7 @@
/delete TDeleteR GET POST
/participants TUsersR GET POST !tutor
/participants/add TAddUserR GET POST !tutor
/participants/exam/#ExamName TExamR GET POST !tutor
/register TRegisterR POST !timeANDcapacityANDcourse-registeredANDregister-group !timeANDtutorial-registered
/communication TCommR GET POST !tutor
/tutor-invite TInviteR GET POST !tutorANDtutor-control
@ -270,20 +281,22 @@
!/#UUID CryptoUUIDDispatchR GET !free -- just redirect
-- !/*{CI FilePath} CryptoFileNameDispatchR GET !free -- Disabled until preliminary check for valid cID exists
/qualification QualificationAllR GET !free
/qualification/#SchoolId QualificationSchoolR GET !free
/qualification/#SchoolId/#QualificationShorthand QualificationR GET POST !free
/qualification QualificationAllR GET !free
/qualification/#SchoolId QualificationSchoolR GET !free
!/qualification/#SchoolId/new QualificationNewR GET POST -- not free
/qualification/#SchoolId/#QualificationShorthand QualificationR GET POST !free
/qualification/#SchoolId/#QualificationShorthand/edit QualificationEditR GET POST -- not free
-- /qualification/#SchoolId/#QualificationShorthand/#CryptoUUIDUser QualificationUserR GET -- see LmsUserR
/qualifications/sap/direct QualificationSAPDirectR GET -- !token -- SAP EXPORT -- TODO reinstate token requirement
/qualifications/sap/direct QualificationSAPDirectR GET -- !token -- SAP EXPORT -- TODO reinstate token requirement
-- LMS
/lms LmsAllR GET POST
/lms/#SchoolId LmsSchoolR GET
/lms/#SchoolId/#QualificationShorthand LmsR GET POST
/lms/#SchoolId/#QualificationShorthand/edit LmsEditR GET POST
-- new V2 LMS Interface
/lms/#SchoolId/#QualificationShorthand/learners LmsLearnersR GET
/lms/#SchoolId/#QualificationShorthand/learners/orphans LmsOrphansR GET
/lms/#SchoolId/#QualificationShorthand/learners/direct LmsLearnersDirectR GET !token -- LMS
/lms/#SchoolId/#QualificationShorthand/report LmsReportR GET POST
/lms/#SchoolId/#QualificationShorthand/report/upload LmsReportUploadR GET POST

View File

@ -289,13 +289,14 @@ in pkgs.mkShell {
# busybox # for print services, but interferes with build commands in develop-shell
htop
pdftk # pdftk just for testing pdf-passwords
roboto roboto-mono
# texlive.combined.scheme-full # works
# texlive.combined.scheme-medium
# texlive.combined.scheme-small
(texlive.combine {
inherit (texlive) scheme-basic
babel-german babel-english booktabs textpos
enumitem eurosym koma-script parskip xcolor dejavu
enumitem eurosym koma-script parskip xcolor roboto xkeyval
luatexbase lualatex-math unicode-math selnolig # required for LuaTeX
;
})

View File

@ -1,4 +1,4 @@
-- SPDX-FileCopyrightText: 2022 Gregor Kleen <gregor.kleen@ifi.lmu.de>,Sarah Vaupel <sarah.vaupel@ifi.lmu.de>,Sarah Vaupel <vaupel.sarah@campus.lmu.de>,Steffen Jost <jost@tcs.ifi.lmu.de>
-- SPDX-FileCopyrightText: 2022-24 Gregor Kleen <gregor.kleen@ifi.lmu.de>,Sarah Vaupel <sarah.vaupel@ifi.lmu.de>,Sarah Vaupel <vaupel.sarah@campus.lmu.de>,Steffen Jost <jost@tcs.ifi.lmu.de>,Steffen Jost <s.jost@fraport.de>
--
-- SPDX-License-Identifier: AGPL-3.0-or-later
@ -115,16 +115,11 @@ import GHC.RTS.Flags (getRTSFlags)
import qualified Prometheus
import qualified Data.IntervalMap.Strict as IntervalMap
import qualified Utils.Pool as Custom
import Utils.Postgresql
import Handler.Utils.Memcached (manageMemcachedLocalInvalidations)
import qualified System.Clock as Clock
import Utils.Avs
import Utils.Avs (mkAvsQuery)
-- Import all relevant handler modules here.
-- (HPack takes care to add new modules to our cabal file nowadays.)
@ -137,6 +132,7 @@ import Handler.Users.Add
import Handler.Admin
import Handler.Term
import Handler.School
import Handler.School.DayTasks
import Handler.Course
import Handler.Sheet
import Handler.Submission
@ -157,6 +153,8 @@ import Handler.Upload
import Handler.Qualification
import Handler.LMS
import Handler.SAP
import Handler.CommCenter
import Handler.MailCenter
import Handler.PrintCenter
import Handler.ApiDocs
import Handler.Swagger
@ -216,18 +214,6 @@ makeFoundation appSettings''@AppSettings{..} = do
appJobState <- liftIO newEmptyTMVarIO
appHealthReport <- liftIO $ newTVarIO Set.empty
appFileSourceARC <- for appFileSourceARCConf $ \ARCConf{..} -> do
ah <- initARCHandle arccMaximumGhost arccMaximumWeight
void . Prometheus.register $ arcMetrics ARCFileSource ah
return ah
appFileSourcePrewarm <- for appFileSourcePrewarmConf $ \PrewarmCacheConf{..} -> do
lh <- initLRUHandle precMaximumWeight
void . Prometheus.register $ lruMetrics LRUFileSourcePrewarm lh
return lh
appFileInjectInhibit <- liftIO $ newTVarIO IntervalMap.empty
for_ (guardOnM (isn't _JobsOffload appJobMode) appInjectFiles) $ \_ ->
void . Prometheus.register $ injectInhibitMetrics appFileInjectInhibit
appStartTime <- liftIO getCurrentTime
-- We need a log function to create a connection pool. We need a connection
-- pool to create our foundation. And we need our foundation to get a
@ -236,7 +222,7 @@ makeFoundation appSettings''@AppSettings{..} = do
-- from there, and then create the real foundation.
let
mkFoundation :: _ -> (forall m. MonadIO m => Custom.Pool' m DBConnLabel DBConnUseState SqlBackend) -> _
mkFoundation appSettings' appConnPool appSmtpPool appLdapPool appCryptoIDKey appSessionStore appSecretBoxKey appWidgetMemcached appJSONWebKeySet appClusterID appMemcached appMemcachedLocal appUploadCache appVerpSecret appAuthKey appPersonalisedSheetFilesSeedKey appVolatileClusterSettingsCache appAvsQuery = UniWorX{..}
mkFoundation appSettings' appConnPool appSmtpPool appLdapPool appCryptoIDKey appSessionStore appSecretBoxKey appWidgetMemcached appJSONWebKeySet appClusterID appMemcached appUploadCache appVerpSecret appAuthKey appPersonalisedSheetFilesSeedKey appVolatileClusterSettingsCache appAvsQuery = UniWorX{..}
tempFoundation = mkFoundation
(error "appSettings' forced in tempFoundation")
(error "connPool forced in tempFoundation")
@ -249,7 +235,6 @@ makeFoundation appSettings''@AppSettings{..} = do
(error "JSONWebKeySet forced in tempFoundation")
(error "ClusterID forced in tempFoundation")
(error "memcached forced in tempFoundation")
(error "memcachedLocal forced in tempFoundation")
(error "MinioConn forced in tempFoundation")
(error "VerpSecret forced in tempFoundation")
(error "AuthKey forced in tempFoundation")
@ -334,12 +319,6 @@ makeFoundation appSettings''@AppSettings{..} = do
$logWarnS "setup" "Clearing memcached"
liftIO $ Memcached.flushAll memcachedConn
return AppMemcached{..}
appMemcachedLocal <- for appMemcachedLocalConf $ \ARCConf{..} -> do
memcachedLocalARC <- initARCHandle arccMaximumGhost arccMaximumWeight
void . Prometheus.register $ arcMetrics ARCMemcachedLocal memcachedLocalARC
memcachedLocalInvalidationQueue <- newTVarIO mempty
memcachedLocalHandleInvalidations <- allocateLinkedAsync . managePostgresqlChannel appDatabaseConf ChannelMemcachedLocalInvalidation $ manageMemcachedLocalInvalidations memcachedLocalARC memcachedLocalInvalidationQueue
return AppMemcachedLocal{..}
appSessionStore <- mkSessionStore appSettings'' sqlPool `customRunSqlPool` sqlPool
@ -352,15 +331,15 @@ makeFoundation appSettings''@AppSettings{..} = do
handleIf isBucketExists (const $ return ()) $ Minio.makeBucket appUploadTmpBucket Nothing
return conn
appAvsQuery <- case appAvsConf of
appAvsQuery <- case appAvsConf of
Nothing -> do
$logErrorS "avsPrepare" "appAvsConfig is empty, i.e. invalid AVS configuration settings."
return Nothing
-- error "AvsConfig is empty, i.e. invalid AVS configuration settings."
Just avsConf -> do
-- error "AvsConfig is empty, i.e. invalid AVS configuration settings."
Just avsConf -> do
manager <- newManagerSettings $ mkManagerSettings (def { settingDisableCertificateValidation = True }) Nothing
let avsServer = BaseUrl
let avsServer = BaseUrl
{ baseUrlScheme = Https
, baseUrlHost = avsHost avsConf
, baseUrlPort = avsPort avsConf
@ -377,7 +356,7 @@ makeFoundation appSettings''@AppSettings{..} = do
$logDebugS "Runtime configuration" $ tshowCrop appSettings'
let foundation = mkFoundation appSettings' sqlPool smtpPool ldapPool appCryptoIDKey appSessionStore appSecretBoxKey appWidgetMemcached appJSONWebKeySet appClusterID appMemcached appMemcachedLocal appUploadCache appVerpSecret appAuthKey appPersonalisedSheetFilesSeedKey appVolatileClusterSettingsCache appAvsQuery
let foundation = mkFoundation appSettings' sqlPool smtpPool ldapPool appCryptoIDKey appSessionStore appSecretBoxKey appWidgetMemcached appJSONWebKeySet appClusterID appMemcached appUploadCache appVerpSecret appAuthKey appPersonalisedSheetFilesSeedKey appVolatileClusterSettingsCache appAvsQuery
-- Return the foundation
$logInfoS "setup" "*** DONE ***"
@ -657,7 +636,7 @@ appMain = runResourceT $ do
notifyWatchdog = forever' Nothing $ \pResults -> do
let delay = floor $ wInterval % 4
d <- liftIO $ newDelay delay
$logDebugS "Notify" $ "Waiting up to " <> tshow delay <> "µs..."
mResults <- atomically $ asum
[ pResults <$ waitDelay d
@ -746,8 +725,8 @@ shutdownApp app = do
-- | Run a handler
handler, handler' :: Handler a -> IO a
handler h = runResourceT $ getAppDevSettings >>= makeFoundation >>= liftIO . flip unsafeHandler h
handler' h = runResourceT $ getAppSettings >>= makeFoundation >>= liftIO . flip unsafeHandler h
handler h = runResourceT $ getAppDevSettings >>= makeFoundation >>= liftIO . flip unsafeHandler h
handler' h = runResourceT $ getAppSettings >>= makeFoundation >>= liftIO . flip unsafeHandler h
-- | Run DB queries
db, db' :: DB a -> IO a

View File

@ -1,7 +1,9 @@
-- SPDX-FileCopyrightText: 2023 Gregor Kleen <gregor.kleen@ifi.lmu.de>,Steffen Jost <s.jost@fraport.de>
-- SPDX-FileCopyrightText: 2023-24 Gregor Kleen <gregor.kleen@ifi.lmu.de>,Steffen Jost <s.jost@fraport.de>
--
-- SPDX-License-Identifier: AGPL-3.0-or-later
{-# LANGUAGE TypeApplications #-}
module Audit
( module Audit.Types
, AuditException(..)
@ -9,6 +11,7 @@ module Audit
, AuditRemoteException(..)
, getRemote
, logInterface, logInterface'
, reportAdminProblem
) where
@ -16,6 +19,8 @@ import Import.NoModel
import Settings
import Model
import Database.Persist.Sql
import qualified Database.Esqueleto.Experimental as E -- needs TypeApplications Lang-Pragma
import qualified Database.Esqueleto.Utils as E
import Audit.Types
import qualified Data.Text as Text
@ -128,7 +133,7 @@ logInterface :: ( AuthId (HandlerSite m) ~ Key User
-> Text -- ^ Any additional information
-> ReaderT (YesodPersistBackend (HandlerSite m)) m ()
-- ^ Log a transaction using information available from `HandlerT`, also calls `audit`
logInterface interfaceLogInterface interfaceLogSubtype interfaceLogSuccess interfaceLogRows interfaceLogInfo = do
logInterface interfaceLogInterface interfaceLogSubtype interfaceLogSuccess interfaceLogRows interfaceLogInfo = do
interfaceLogWrite <- (methodGet /=) . Wai.requestMethod . reqWaiRequest <$> getRequest
logInterface' interfaceLogInterface interfaceLogSubtype interfaceLogWrite interfaceLogSuccess interfaceLogRows interfaceLogInfo
@ -152,7 +157,7 @@ logInterface' :: ( AuthId (HandlerSite m) ~ Key User
-- ^ Log a transaction using information available from `HandlerT`, also calls `audit`
logInterface' (Text.strip -> interfaceLogInterface) (Text.strip -> interfaceLogSubtype) interfaceLogWrite interfaceLogSuccess interfaceLogRows (Text.strip -> interfaceLogInfo) = do
interfaceLogTime <- liftIO getCurrentTime
-- deleteBy $ UniqueInterfaceSubtypeWrite interfaceLogInterface interfaceLogSubtype interfaceLogWrite -- always replace: deleteBy & insert seems to be safest and fastest
-- deleteBy $ UniqueInterfaceSubtypeWrite interfaceLogInterface interfaceLogSubtype interfaceLogWrite -- deleteBy & insert would be justified here, leading to a new Row-ID, since the two rows are not truly connected.
-- insert_ InterfaceLog{..}
void $ upsertBy (UniqueInterfaceSubtypeWrite interfaceLogInterface interfaceLogSubtype interfaceLogWrite)
( InterfaceLog{..} )
@ -169,3 +174,28 @@ logInterface' (Text.strip -> interfaceLogInterface) (Text.strip -> interfaceLogS
, transactionInterfaceInfo = interfaceLogInfo
, transactionInterfaceSuccess = Just interfaceLogSuccess
}
reportAdminProblem :: ( IsSqlBackend (YesodPersistBackend (HandlerSite m))
, SqlBackendCanWrite (YesodPersistBackend (HandlerSite m))
, MonadHandler m
-- , HasCallStack
)
=> AdminProblem -- ^ Problem to record
-> ReaderT (YesodPersistBackend (HandlerSite m)) m ()
-- ^ Log a problem that needs interventions by admins, provided this problem has not already been reported and is still unsolved
--
-- - `problemLogTime` is now
-- - `problemSolver` is Nothing, we do not record the person who caused it
reportAdminProblem problem = do
let problemLogSolved = Nothing
problemLogSolver = Nothing
problemLogInfo = toJSON problem
problemLogTime <- liftIO getCurrentTime
isKnown <- E.selectExists $ do
pl <- E.from $ E.table @ProblemLog
E.where_ $ E.isNothing (pl E.^. ProblemLogSolved)
E.&&. E.val problemLogInfo E.==. pl E.^. ProblemLogInfo
unless isKnown $ insert_ ProblemLog{..}
$logWarnS "Problem" $ Text.filter (/= '\n') $ tshow problem -- <> " - " <> pack (prettyCallStack callStack)

View File

@ -1,15 +1,18 @@
-- SPDX-FileCopyrightText: 2022-23 Gregor Kleen <gregor.kleen@ifi.lmu.de>,Sarah Vaupel <vaupel.sarah@campus.lmu.de>,Steffen Jost <s.jost@fraport.de>
-- SPDX-FileCopyrightText: 2022-24 Gregor Kleen <gregor.kleen@ifi.lmu.de>,Sarah Vaupel <vaupel.sarah@campus.lmu.de>,Steffen Jost <s.jost@fraport.de>
--
-- SPDX-License-Identifier: AGPL-3.0-or-later
module Audit.Types
( Transaction(..)
, AdminProblem(..)
, decodeAdminProblem
) where
import ClassyPrelude.Yesod hiding (derivePersistFieldJSON)
import Model.Types.TH.JSON
import Model
import Data.Aeson
import Data.Aeson.TH
import Utils.PathPiece
@ -182,7 +185,7 @@ data Transaction
}
| TransactionLmsStart
{ transactionQualification :: QualificationId
, transactionLmsIdent :: LmsIdent
, transactionLmsIdent :: LmsIdent
, transactionLmsUser :: UserId
, transactionLmsUserKey :: LmsUserId
}
@ -210,10 +213,16 @@ data Transaction
, transactionNote :: Maybe Text
, transactionReceived :: UTCTime -- when was the csv file received?
}
| TransactionLmsTerminated
{ transactionQualification :: QualificationId
, transactionLmsIdent :: LmsIdent
, transactionLmsUser :: UserId
, transactionNote :: Maybe Text
}
| TransactionQualificationUserEdit -- Note that a renewal always entails unblocking as well!
{ transactionUser :: UserId -- qualification holder that is updated
, transactionQualificationUser :: QualificationUserId -- not really necessary, maybe remove?
, transactionQualification :: QualificationId
, transactionQualification :: QualificationId
, transactionQualificationValidUntil :: Day
, transactionQualificationScheduleRenewal :: Maybe Bool -- Maybe, because some update may leave it unchanged (also avoids DB Migration)
, transactionNote :: Maybe Text
@ -251,4 +260,64 @@ deriveJSON defaultOptions
, sumEncoding = TaggedObject "transaction" "data"
} ''Transaction
derivePersistFieldJSON ''Transaction
derivePersistFieldJSON ''Transaction
-- Datatype for raising admin awareness to certain problems
-- Database stores generic Value in table ProblemLog, such that changes do not disturb old entries
-- Note that there is no RenderMessage instance, instead see @Handler.Admin.adminProblemCell dealing with special cases instead
-- Note: Adjust MsgAdminProblemInfoTooltip as well
data AdminProblem
= AdminProblemNewCompany -- new company was noticed, presumably without supervisors
{ adminProblemCompany :: CompanyId
}
| AdminProblemSupervisorNewCompany
{ adminProblemUser :: UserId -- a default supervisor has changed company
, adminProblemCompany :: CompanyId -- old company where the user had default supervisor rights
, adminProblemCompanyNew :: CompanyId -- new company of the user
, adminProblemSupervisorReroute :: Bool -- reroute included?
}
| AdminProblemSupervisorLeftCompany
{ adminProblemUser :: UserId -- user who had a supervisor but no longer has, due to supervisor change
, adminProblemCompany :: CompanyId -- old company
, adminProblemSupervisorReroute :: Bool -- reroute included?
}
| AdminProblemCompanySuperiorChange -- a company received a new superior user through AVS
{ adminProblemUser :: UserId -- new superior user
, adminProblemCompany :: CompanyId -- affected company
, adminProblemUserOld :: Maybe UserId -- previous superior
}
| AdminProblemCompanySuperiorNotFound -- a company received a new superior user through AVS, but user could not be created from email
{ adminProblemUser :: UserId -- user who had a supervisor but no longer has, due to supervisor change
, adminProblemEmail :: Maybe Text -- new superior user's email, not found in LDAP
, adminProblemCompany :: CompanyId -- affected company
, adminProblemUserOld :: Maybe UserId -- previous superior
}
| AdminProblemNewlyUnsupervised
{ adminProblemUser :: UserId -- user who had a supervisor but no longer has, due to user company change
, adminProblemCompanyOld :: Maybe CompanyId -- old company
, adminProblemCompanyNew :: CompanyId -- new company of the user
}
| AdminProblemUnknown -- miscellanous problem, just displaying text
{ adminProblemText :: Text
}
deriving (Eq, Ord, Read, Show, Generic)
-- Columns shown in problem table: adminProblemCompany, adminProblemUser
-- For display: add clause to Handler.Admin.adminProblemCell
deriveJSON defaultOptions
{ constructorTagModifier = camelToPathPiece' 2
, fieldLabelModifier = camelToPathPiece' 2
, tagSingleConstructors = True
, sumEncoding = TaggedObject "problem" "data"
, rejectUnknownFields = False
} ''AdminProblem
derivePersistFieldJSON ''AdminProblem
decodeAdminProblem :: Value -> AdminProblem
decodeAdminProblem v = case fromJSON v of
Error msg -> AdminProblemUnknown $ pack msg
Success p -> p

View File

@ -34,7 +34,7 @@ dummyForm = do
mr <- getMessageRender
wreq (ciField & addDatalist userList) (fslpI MsgDummyIdent (mr MsgDummyIdentPlaceholder) & addAttr "autocomplete" "username" & addName PostLoginDummy) Nothing
where
userList = fmap mkOptionList . runDB $ withReaderT projectBackend (map toOption <$> selectList [] [Asc UserIdent] :: ReaderT SqlBackend _ [Option UserIdent])
userList = fmap mkOptionList . runDB $ withReaderT projectBackend (map toOption <$> selectList [UserId <=. UserKey 12] [Asc UserIdent] :: ReaderT SqlBackend _ [Option UserIdent])
toOption (Entity _ User{..}) = Option userDisplayName userIdent (CI.original userIdent)
apDummy :: Text

View File

@ -1,7 +1,6 @@
-- {-# LANGUAGE BangPatterns #-}
{-# OPTIONS_GHC -Wwarn #-}
{-# OPTIONS_GHC -Wwarn -fno-warn-orphans #-}
-- SPDX-FileCopyrightText: 2024-2025 Sarah Vaupel <sarah.vaupel@uniworx.de>
-- SPDX-FileCopyrightText: 2024 Sarah Vaupel <sarah.vaupel@uniworx.de>
--
-- SPDX-License-Identifier: AGPL-3.0-or-later
@ -64,8 +63,9 @@ foreign import ccall unsafe "sodium_bin2hex"
bin2hex :: ByteString -> String
bin2hex bs = let tlen = S.length bs * 2 + 1 in
S8.unpack . S8.init . snd . buildUnsafeByteString tlen $ \t ->
constByteStrings [bs] $ \[(pbs, _)] ->
c_sodium_bin2hex t (fromIntegral tlen) pbs (fromIntegral $ S.length bs)
let aux [(pbs, _)] = c_sodium_bin2hex t (fromIntegral tlen) pbs (fromIntegral $ S.length bs)
aux _ = error "Crypto.Saltine.Instances.bin2hex reached an impossible computation path"
in constByteStrings [bs] aux
instance Show Key where
show k = "SecretBox.Key {hashesTo = \"" <> (bin2hex . shorthash nullShKey $ encode k) <> "}\""

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