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 .kateproject
src/Handler/Assist.bak src/Handler/Assist.bak
src/Handler/Course.SnapCustom.hs src/Handler/Course.SnapCustom.hs
frontend/src/env.sass
*.orig *.orig
/instance /instance
.stack-work-* .stack-work-*

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

@ -55,12 +55,12 @@ my %parKinds = (
}, },
autokind=>{ autokind=>{
arity=>1, 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', help=>'determine the tag kind from branch name instead of fixed value; use the first fitting glob',
}, },
change=>{ change=>{
arity=>1, 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', 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=>{ changelog=>{
@ -143,7 +143,6 @@ if($par{autokind}) {
my @rules = split /,/, $par{autokind}; my @rules = split /,/, $par{autokind};
RULES: { RULES: {
for my $r(@rules) { for my $r(@rules) {
warn "$0: Processing autokind rule '$r'\n" if $par{v};
if($r!~m#(.*)=(.*)#) { if($r!~m#(.*)=(.*)#) {
die "$0: Bad rule in autokind: $r\n"; die "$0: Bad rule in autokind: $r\n";
} }
@ -159,15 +158,14 @@ if($par{autokind}) {
$branchNameEscaped =~ s/[^0-9a-zA-Z]+/-/g; $branchNameEscaped =~ s/[^0-9a-zA-Z]+/-/g;
if($par{'v'}) { if($par{'v'}) {
warn "VERBOSE: Parameters\n"; print "VERBOSE: Parameters\n";
for my $k(sort keys %par) { for my $k(sort keys %par) {
warn " $k: $par{$k}\n" print " $k: $par{$k}\n"
} }
} }
my %typeReact = (); my %typeReact = ();
for my $as(split /,/, $par{change}) { for my $as(split /,/, $par{change}) {
warn "$0: processing change parameter '$as'\n" if $par{v};
if($as=~m#(.*)=(.*)#) { if($as=~m#(.*)=(.*)#) {
$typeReact{$1} = $2; $typeReact{$1} = $2;
} else { } else {
@ -246,21 +244,16 @@ sub parseVersion {
warn "$0: unexpected old version number: $v\n" if $par{v}; warn "$0: unexpected old version number: $v\n" if $par{v};
return undef return undef
} }
$cap{pre} = 'v' if '' eq $cap{pre}; $pre = 'v' if '' eq $pre;
my %ret = ( return {
prefix=>$cap{pre}, prefix=>$pre,
major=>$cap{ma}, major=>$ma,
minor=>$cap{mi}, minor=>$mi,
patch=>$cap{p}, patch=>$p,
subpatch=>$cap{sp}, subpatch=>$sp,
branchname=>$cap{brn}, branchname=>$brn,
branchversion=>$cap{brv}, branchversion=>$brv,
);
if($par{v}) {
my $parsed = join '; ', map { "$_=>".($ret{$_}//'') } sort keys %ret;
warn "Version '$v' was parsed to '$parsed'\n"
} }
return \%ret
} }
#@oldVersions = sort { #@oldVersions = sort {
@ -300,7 +293,7 @@ sub vsCompare {
($v->{minor} // 0) <=> ($w->{minor} // 0) || ($v->{minor} // 0) <=> ($w->{minor} // 0) ||
($v->{patch} // 0) <=> ($w->{patch} // 0) || ($v->{patch} // 0) <=> ($w->{patch} // 0) ||
($v->{branchname} // '') cmp ($w->{branchname} // '') || ($v->{branchname} // '') cmp ($w->{branchname} // '') ||
($v->{branchversion} // 0) <=> ($w->{branchversion} // 0) || ($v->{branchversion} // '') <=> ($w->{branchversion} // '') ||
($v->{subpatch} // '') cmp ($w->{subpatch} // '') ($v->{subpatch} // '') cmp ($w->{subpatch} // '')
) )
} elsif($v->{prefix}=~m/^v?$/ and !$w->{prefix}=~m/^v?$/) { } elsif($v->{prefix}=~m/^v?$/ and !$w->{prefix}=~m/^v?$/) {
@ -376,7 +369,6 @@ if('-' eq $par{vcslog}) {
} }
my @versions = (); my @versions = ();
for my $v(@versionsOrig) { for my $v(@versionsOrig) {
warn "$0: Processing orig version (part 1): '$v'\n" if $par{v};
if($v=~m#^(.*?\S)\s*::::\s*(.*?)\s*::::\s*(.*)#) { if($v=~m#^(.*?\S)\s*::::\s*(.*?)\s*::::\s*(.*)#) {
push @versions, { push @versions, {
hash => $1, hash => $1,
@ -394,7 +386,6 @@ my $tag = undef;
my @versionPast = (); my @versionPast = ();
VERSION: for my $v(@versions) { 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(.*)\)#) { #if($v->{meta}=~m#tag\s*:\s*\Q$par{kind}\E(.*)\)#) {
# $tag=$1; # $tag=$1;
# last VERSION # last VERSION
@ -424,7 +415,6 @@ VERSION: for my $v(@versions) {
#$tag = parseVersion($tag); #$tag = parseVersion($tag);
for my $r(reverse @change) { for my $r(reverse @change) {
warn "$0: Processing change: $r\n" if $par{v};
if('major' eq $r->{react}) { if('major' eq $r->{react}) {
$tag->{major}++; $tag->{major}++;
$tag->{minor}=0; $tag->{minor}=0;
@ -474,7 +464,6 @@ my $highStart = $mainVersion ? $sortAll[0] : $sortSee[0];
my $highSee = $sortSee[0]; my $highSee = $sortSee[0];
my %reactCollect = (); my %reactCollect = ();
SEARCHVERSION: for my $v(@versions) { SEARCHVERSION: for my $v(@versions) {
warn "$0: search for version: '$v'\n" if $par{v};
next unless $v->{version}; next unless $v->{version};
next unless $v->{react}; next unless $v->{react};
$reactCollect{$v->{react}} = 1; $reactCollect{$v->{react}} = 1;
@ -486,12 +475,10 @@ SEARCHVERSION: for my $v(@versions) {
sub justVersionInc { sub justVersionInc {
my ($v, $react) = @_; my ($v, $react) = @_;
my $vv = parseVersion($v); 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->{minor}++; $vv->{patch}=0} if $react->{minor};
do {$vv->{major}++; $vv->{minor}=0; $vv->{patch}=0} if $react->{major}; do {$vv->{major}++; $vv->{minor}=0; $vv->{patch}=0} if $react->{major};
my $ret = vsJustVersion($vv); return vsJustVersion($vv);
warn "$0: version inc from '$v' to $ret\n" if $par{v};
return $ret
} }
my $newVersion = undef; my $newVersion = undef;
@ -514,7 +501,6 @@ for(@allVersions) {
$allVersions{$_} = 1 $allVersions{$_} = 1
} }
while(exists $allVersions{$newVersion}) { while(exists $allVersions{$newVersion}) {
warn "$0: Version conflict, so we try another version, '$newVersion' exists already\n" if $par{v};
if($mainVersion) { if($mainVersion) {
die "$0: probably internal error (collision in main version)\n" die "$0: probably internal error (collision in main version)\n"
} }
@ -544,7 +530,6 @@ if($par{changelog}) {
my %seen = (); my %seen = ();
my @sects = ([]); my @sects = ([]);
for(@changelog) { for(@changelog) {
warn "$0: Changelog processing: '$_'\n" if $par{v};
push @sects, [] if m/^## /; push @sects, [] if m/^## /;
push @{$sects[-1]}, $_; push @{$sects[-1]}, $_;
if(m#/commit/([a-f0-9]+)\s*\)\s*\)\s*$#) { if(m#/commit/([a-f0-9]+)\s*\)\s*\)\s*$#) {
@ -558,7 +543,6 @@ if($par{changelog}) {
shift @sects; shift @sects;
} }
for my $s(@sects) { for my $s(@sects) {
warn "$0: Changelog processing, section search: '$s'\n" if $par{v};
my $hh = $s->[0]; my $hh = $s->[0];
chomp $hh; chomp $hh;
my $cnt = @$s; my $cnt = @$s;
@ -583,7 +567,6 @@ if($par{changelog}) {
'feature' => 'Features', 'feature' => 'Features',
); );
SELECTCHANGELOG: for my $v(@versions) { SELECTCHANGELOG: for my $v(@versions) {
warn "$0: Changelog processing, version selection: '$v'\n" if $par{v};
last SELECTCHANGELOG if $seen{$v->{hash}}; last SELECTCHANGELOG if $seen{$v->{hash}};
next unless $v->{subject}=~m#^\s*([a-z]+)\s*(!?)\s*((?:\(.*?\))?)\s*:\s*(.*?)\s*$#i; next unless $v->{subject}=~m#^\s*([a-z]+)\s*(!?)\s*((?:\(.*?\))?)\s*:\s*(.*?)\s*$#i;
my ($kind, $break, $context, $msg) = ($1, $2, $3, $4); 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 = { module.exports = {
scripts: { scripts: {
// postbump: './sync-versions.hs && git add -- package.yaml', // moved to bumpFiles // 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'], packageFiles: ['package.json', 'package.yaml'],
bumpFiles: [ bumpFiles: [
{ {
filename: 'package.json', filename: 'package.json',
type: 'json', type: 'json'
}, },
{ {
filename: 'package-lock.json', filename: 'package-lock.json',
type: 'json', type: 'json'
}, },
{ {
filename: 'package.yaml', filename: 'package.yaml',
updater: standardVersionUpdaterYaml, updater: standardVersionUpdaterYaml
}, },
{ {
filename: 'nix/docker/version.json', filename: 'nix/docker/version.json',
type: 'json', type: 'json'
}, },
{ {
filename: 'nix/docker/demo-version.json', filename: 'nix/docker/demo-version.json',
type: 'json', type: 'json'
}, }
], ],
commitUrlFormat: 'https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/{{hash}}', commitUrlFormat: 'https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/{{hash}}',
compareUrlFormat: 'https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/{{previousTag}}...{{currentTag}}', compareUrlFormat: 'https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/{{previousTag}}...{{currentTag}}',
issueUrlFormat: 'https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/issues/{{id}}', 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-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) ## [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 ### 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)) * **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)) * **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 ### Bug Fixes
* **stack.yaml:** move to uniworx.de gitlab ([55484e6](https://fraport@dev.azure.com/fraport/Fahrerausbildung/_git/FRADrive/commit/55484e631b786ea3710d322282019baf5292c243)) * **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 CONTAINER_IDENT
export CF_PREFIX export CF_PREFIX
export DEVELOP export DEVELOP
export MOUNT_DIR=/mnt/fradrive
export CONTAINER_ATTACHED export CONTAINER_ATTACHED
export CONTAINER_INIT export CONTAINER_INIT
export CONTAINER_CLEANUP export CONTAINER_CLEANUP
export PROJECT_DIR=/fradrive
export SERVICE export SERVICE
export SERVICE_VARIANT ?= $(SERVICE) export SERVICE_VARIANT ?= $(SERVICE)
export JOB export JOB
export IMAGE export CONTAINER_CMD
export SET_IMAGE export SET_CONTAINER_CMD
export ENTRYPOINT export ENTRYPOINT
export EXEC_OPTS 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) # HELP: stop all running containers and remove all compilation results in the directory (but leave images including dependencies unharmed)
clean: clean:
rm -rf develop 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 .stack-work .stack-work.lock
-rm -rf bin .Dockerfile develop -rm -rf bin .Dockerfile develop
-$(CONTAINER_COMMAND) container prune --force -$(CONTAINER_COMMAND) container prune --force
@ -84,7 +84,6 @@ clean-all: clean-images
.PHONY: release .PHONY: release
# HELP: create, commit and push a new release # HELP: create, commit and push a new release
# TODO: only release when build and tests are passing!!!
release: release:
VERSION=`./utils/version.pl -changelog CHANGELOG.md -v` ; \ VERSION=`./utils/version.pl -changelog CHANGELOG.md -v` ; \
git add CHANGELOG.md ; \ git add CHANGELOG.md ; \
@ -110,24 +109,24 @@ start:
.PHONY: %-backend .PHONY: %-backend
%-backend: SERVICE=backend %-backend: SERVICE=backend
%-backend: SERVICE_VARIANT=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" %-backend: BASE_PORTS = "DEV_PORT_HTTP=3000" "DEV_PORT_HTTPS=3443"
.PHONY: %-uniworxdb .PHONY: %-uniworxdb
%-uniworxdb: SERVICE=backend %-uniworxdb: SERVICE=backend
%-uniworxdb: SERVICE_VARIANT=uniworxdb %-uniworxdb: SERVICE_VARIANT=uniworxdb
%-uniworxdb: IMAGE=localhost/fradrive/backend %-uniworxdb: CONTAINER_CMD=localhost/fradrive/backend
.PHONY: %-ghci .PHONY: %-ghci
%-ghci: SERVICE=backend %-ghci: SERVICE=backend
%-ghci: SERVICE_VARIANT=ghci %-ghci: SERVICE_VARIANT=ghci
%-ghci: IMAGE=localhost/fradrive/backend %-ghci: CONTAINER_CMD=localhost/fradrive/backend
.PHONY: %-hoogle .PHONY: %-hoogle
%-hoogle: SERVICE=backend %-hoogle: SERVICE=backend
%-hoogle: SERVICE_VARIANT=hoogle %-hoogle: SERVICE_VARIANT=hoogle
%-hoogle: BASE_PORTS = "HOOGLE_PORT=8081" %-hoogle: BASE_PORTS = "HOOGLE_PORT=8081"
%-hoogle: IMAGE=localhost/fradrive/backend %-hoogle: CONTAINER_CMD=localhost/fradrive/backend
--start-hoogle: --start-hoogle:
HOOGLE_PORT=`cat $(CONTAINER_FILE) | grep 'HOOGLE_PORT=' | sed 's/HOOGLE_PORT=//'` ; \ HOOGLE_PORT=`cat $(CONTAINER_FILE) | grep 'HOOGLE_PORT=' | sed 's/HOOGLE_PORT=//'` ; \
stack $(STACK_CORES) hoogle -- server --local --port $${HOOGLE_PORT} stack $(STACK_CORES) hoogle -- server --local --port $${HOOGLE_PORT}
@ -135,24 +134,24 @@ start:
.PHONY: %-frontend .PHONY: %-frontend
%-frontend: SERVICE=frontend %-frontend: SERVICE=frontend
%-frontend: SERVICE_VARIANT=frontend %-frontend: SERVICE_VARIANT=frontend
%-frontend: IMAGE=localhost/fradrive/frontend %-frontend: CONTAINER_CMD=localhost/fradrive/frontend
.PHONY: %-postgres .PHONY: %-postgres
%-postgres: SERVICE=postgres %-postgres: SERVICE=postgres
%-postgres: SERVICE_VARIANT=postgres %-postgres: SERVICE_VARIANT=postgres
%-postgres: BASE_PORTS = "PGPORT=5432" %-postgres: BASE_PORTS = "PGPORT=5432"
%-postgres: IMAGE=localhost/fradrive/postgres %-postgres: CONTAINER_CMD=localhost/fradrive/postgres
.PHONY: %-memcached .PHONY: %-memcached
%-memcached: SERVICE=memcached %-memcached: SERVICE=memcached
%-memcached: SERVICE_VARIANT=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" %-memcached: BASE_PORTS = "MEMCACHED_PORT=11211"
.PHONY: %-minio .PHONY: %-minio
%-minio: SERVICE=minio %-minio: SERVICE=minio
%-minio: SERVICE_VARIANT=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" %-minio: BASE_PORTS = "UPLOAD_S3_PORT=9000"
.PHONY: start-% .PHONY: start-%
@ -214,13 +213,18 @@ ghci: shell-ghci;
rebuild-%: rebuild-%:
$(MAKE) -- --image-build SERVICE=$* NO_CACHE=--no-cache $(MAKE) -- --image-build SERVICE=$* NO_CACHE=--no-cache
--image-build: --image-build:
ifeq "$(IMAGE)" "localhost/fradrive/$(SERVICE)" ifeq "$(CONTAINER_CMD)" "localhost/fradrive/$(SERVICE)"
rm -f .Dockerfile rm -f .Dockerfile
ln -s docker/$(SERVICE)/Dockerfile .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 \ if [ "$(IN_CONTAINER)" == "false" ] ; then \
$(CONTAINER_COMMAND) build $(NO_CACHE) \ $(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} \ --build-arg PROJECT_DIR=$${PROJECT_DIR} \
--env IN_CONTAINER=true \ --env IN_CONTAINER=true \
--env JOB=$(JOB) \ --env JOB=$(JOB) \
@ -235,22 +239,22 @@ endif
DEVELOP=`cat develop/.current` ; \ DEVELOP=`cat develop/.current` ; \
./utils/watchcontainerrun.sh "$(CONTAINER_COMMAND)" "$(CONTAINER_FILE)" "$(CONTAINER_INIT)" "$(CONTAINER_CLEANUP)" & \ ./utils/watchcontainerrun.sh "$(CONTAINER_COMMAND)" "$(CONTAINER_FILE)" "$(CONTAINER_INIT)" "$(CONTAINER_CLEANUP)" & \
CONTAINER_NAME=fradrive.$(CURR_DEV).$(CONTAINER_IDENT) ; \ CONTAINER_NAME=fradrive.$(CURR_DEV).$(CONTAINER_IDENT) ; \
if ! [ -z "$(SET_IMAGE)" ] ; \ if ! [ -z "$(SET_CONTAINER_CMD)" ] ; \
then \ then \
IMAGE="$(SET_IMAGE)" ; \ CONTAINER_CMD="$(SET_CONTAINER_CMD)" ; \
else \ else \
IMAGE=$(IMAGE) ; \ CONTAINER_CMD=$(CONTAINER_CMD) ; \
fi ; \ fi ; \
CONTAINER_ID=`$(CONTAINER_BGRUN) \ CONTAINER_ID=`$(CONTAINER_BGRUN) \
-v $(PWD):$(PROJECT_DIR):rw \ -v $(PWD):$(MOUNT_DIR) \
--env IN_CONTAINER=true \ --env IN_CONTAINER=true \
--env FRADRIVE_MAKE_TARGET="--$(JOB)-$(SERVICE_VARIANT)" \
--env CONTAINER_FILE=$(CONTAINER_FILE) \ --env CONTAINER_FILE=$(CONTAINER_FILE) \
--env CONTAINER_NAME=$${CONTAINER_NAME} \ --env CONTAINER_NAME=$${CONTAINER_NAME} \
--env JOB=$(JOB) \ --env JOB=$(JOB) \
--env SRC=$(SRC) \ --env SRC=$(SRC) \
--name $${CONTAINER_NAME} \ --name $${CONTAINER_NAME} \
$${IMAGE} \ $${CONTAINER_CMD} \
make -- --$(JOB)-$(SERVICE_VARIANT) IN_CONTAINER=true \
` ; \ ` ; \
printf "CONTAINER_ID=$${CONTAINER_ID}" >> "$(CONTAINER_FILE)" ; \ printf "CONTAINER_ID=$${CONTAINER_ID}" >> "$(CONTAINER_FILE)" ; \
if [[ "true" == "$(CONTAINER_ATTACHED)" ]] ; then \ if [[ "true" == "$(CONTAINER_ATTACHED)" ]] ; then \
@ -258,6 +262,7 @@ endif
fi fi
# For Reverse Proxy Problem see: https://groups.google.com/g/yesodweb/c/2EO53kSOuy0/m/Lw6tq2VYat4J # For Reverse Proxy Problem see: https://groups.google.com/g/yesodweb/c/2EO53kSOuy0/m/Lw6tq2VYat4J
# HELP(start-backend): start development instance # HELP(start-backend): start development instance
--start-backend: --start-backend:
export YESOD_IP_FROM_HEADER=true; \ export YESOD_IP_FROM_HEADER=true; \
@ -282,23 +287,22 @@ endif
--compile-backend: --compile-backend:
stack build $(STACK_CORES) --fast --profile --library-profiling --executable-profiling --flag uniworx:-library-only $(--DEVELOPMENT) --local-bin-path $$(pwd)/bin --copy-bins 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 # HELP(dependencies-backend): (re-)build backend dependencies
--dependencies-backend: #uniworx.cabal --dependencies-backend: uniworx.cabal
chown -R `id -un`:`id -gn` "$(PROJECT_DIR)"; \ stack build $(STACK_CORES) --fast --only-dependencies
stack build -j2 --only-dependencies
# HELP(lint-backend): lint backend # HELP(lint-backend): lint backend
--lint-backend: --lint-backend:
stack build $(STACK_CORES) --test --fast --flag uniworx:library-only $(--DEVELOPMENT) uniworx:test:hlint stack build $(STACK_CORES) --test --fast --flag uniworx:library-only $(--DEVELOPMENT) uniworx:test:hlint
# HELP(test-backend): test backend # HELP(test-backend): test backend
--test-backend: --test-backend:
stack build $(STACK_CORES) --test --coverage --fast --flag uniworx:library-only $(--DEVELOPMENT) stack build $(STACK_CORES) --test --coverage --fast --flag uniworx:library-only $(--DEVELOPMENT)
# uniworx.cabal: uniworx.cabal:
# stack exec -- hpack --force stack exec -- hpack --force
# HELP(compile-frontend): compile frontend assets # 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 npm run build
--start-frontend: --compile-frontend; --start-frontend: --compile-frontend;
--dependencies-frontend: node_modules assets; --dependencies-frontend: node_modules assets static well-known;
node_modules: package.json package-lock.json node_modules: package.json package-lock.json
npm install --cache .npm --prefer-offline npm install --cache .npm --prefer-offline
package-lock.json: package.json 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/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 ./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 -cp assets/icons-src/*.svg assets/icons/fradrive
frontend/src/env.sass: static: node_modules assets esbuild.config.mjs
echo "\$$path: '$${PROJECT_DIR}'" > frontend/src/env.sass
static: node_modules assets esbuild.config.mjs frontend/src/env.sass
npm run build npm run build
well-known: static; 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) # 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) # 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} ; \ AVSPASS=${AVSPASS:-nopasswordset} ; \
./bin/uniworxdb $(UNIWORXDB_OPTS) ./bin/uniworxdb $(UNIWORXDB_OPTS)
# HELP(shell-ghci): enter ghci shell. Use "make ghci SRC=<MODULE_FILE.hs>" to load specific source modules."
--shell-ghci: --shell-ghci:
stack ghci -- $(SRC) stack ghci -- $(SRC)
# --main-is uniworx:exe:uniworx # --main-is uniworx:exe:uniworx

View File

@ -29,6 +29,7 @@
"file-upload": "file-arrow-up", "file-upload": "file-arrow-up",
"file-zip": "file-zipper", "file-zip": "file-zipper",
"file-csv": "file-csv", "file-csv": "file-csv",
"file-missing": "file-circle-minus",
"sft-question": "circle-question", "sft-question": "circle-question",
"sft-hint": "life-ring", "sft-hint": "life-ring",
"sft-solution": "circle-exclamation", "sft-solution": "circle-exclamation",
@ -76,12 +77,13 @@
"submission-no-users": "user-slash", "submission-no-users": "user-slash",
"reset": "arrow-rotate-left", "reset": "arrow-rotate-left",
"blocked": "ban", "blocked": "ban",
"certificate": "certificate", "certificate": "car-side",
"print-center": "envelopes-bulk", "print-center": "envelopes-bulk",
"letter": "envelopes-bulk", "letter": "envelopes-bulk",
"at": "at", "at": "at",
"supervisor": "person", "supervisor": "person",
"supervisor-foreign": "person-rays", "supervisor-foreign": "person-rays",
"superior": "user-tie",
"waiting-for-user": "user-gear", "waiting-for-user": "user-gear",
"expired": "hourglass-end", "expired": "hourglass-end",
"locked": "lock", "locked": "lock",
@ -89,9 +91,18 @@
"trash": "trash", "trash": "trash",
"reset-tries": "trash-can-arrow-up", "reset-tries": "trash-can-arrow-up",
"company": "building", "company": "building",
"company-warning": "building-circle-exclamation",
"edit": "pen-to-square", "edit": "pen-to-square",
"user-edit": "user-pen", "user-edit": "user-pen",
"loading": "spinner", "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 # 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' pool: 'Prod Private Agent Pool'
stages: jobs:
# - job: HelloWorld
- stage: Setup # container:
jobs: # image: 'devfra.azurecr.io/de.fraport.trusted/ubuntu:22.04'
- ${{ each service in parameters.services }}: # endpoint: devfra
- template: .azure-pipelines/templates/jobs/setup_image.yaml # steps:
parameters: # - script: echo Hello, world!
imageName: ${{service.name}} # displayName: 'Run a one-line script'
imageBase: ${{service.imageBase}} # - script: |
- template: .azure-pipelines/templates/jobs/setup_dependencies.yaml # echo Add other tasks to build, test, and deploy your project.
parameters: # echo See https://aka.ms/yaml
serviceName: ${{service.name}} # displayName: 'Run a multi-line script'
dependenciesCaches: ${{service.dependenciesCaches}} - job: DockerTaskTest
dependenciesBuildPool: ${{service.buildPool}} container:
dependenciesBuildCores: ${{service.buildCores}} image: devfra.azurecr.io/de.fraport.build/tools:1.1.0
dependenciesBuildTimeout: ${{service.buildTimeout}} endpoint: devfra
steps:
- stage: Build - task: Docker@2
dependsOn: Setup name: dockerLoginDevFra
jobs: displayName: Docker Login to devfra
- ${{ each service in parameters.services }}: inputs:
- job: Build_${{service.name}} command: login
displayName: Compile ${{service.name}} containerRegistry: devFra
dependsOn: ${{service.dependsOn}} - task: Docker@2
pool: '${{service.buildPool}}' name: dockerBuild
timeoutInMinutes: ${{service.buildTimeout}} displayName: Backend image build test
container: inputs:
${{ if eq(variables.setupImages, true) }}: command: build
image: $(buildImageUpstream)/${{service.name}}:$(Build.BuildNumber) Dockerfile: docker/backend/Dockerfile
${{ else }}: buildContext: .
image: $(buildImageUpstream)/${{service.name}}:latest tags: |
endpoint: devfra $(Build.BuildNumber)
env: backend
PROJECT_DIR: $(Build.Repository.LocalPath) arguments: |
IN_CONTAINER: true --build-arg HTTPS_PROXY=http://proxy.frankfurt-airport.de:8080
IN_CI: true --build-arg HTTP_PROXY=http://proxy.frankfurt-airport.de:8080
steps: --build-arg NO_PROXY='localhost,127.0.0.1,*.docker.internal,*.azmk8s.io,devfra.azurecr.io,devfra.westeurope.data.azurecr.io'
- ${{ each dependencyCache in service.dependenciesCaches }}: --build-arg PROJECT_DIR=/fradrive
- template: .azure-pipelines/templates/steps/cache.yaml --build-arg MOUNT_DIR=/mnt/fradrive
parameters: # - job: BuildKitTest
cacheIdent: '${{service.name}}-dependencies' # container:
cacheKeys: '${{dependencyCache.key}}' # image: 'devfra.azurecr.io/de.fraport.trusted/buildkit:0.12.1'
cachePath: '${{dependencyCache.path}}' # endpoint: devfra
- ${{ each dependency in service.dependsOn }}: # steps:
- template: .azure-pipelines/templates/steps/artifact-download.yaml # - script: buildctl build \
parameters: # --frontend=dockerfile.v0 \
artifactName: '${{dependency}}' # --local context=. \
- template: .azure-pipelines/templates/steps/make.yaml # --local dockerfile=docker/backend/Dockerfile
parameters: # displayName: BuildKit test
makeJob: compile # - job: CustomBuildahTest
makeService: ${{service.name}} # container:
makeVars: 'CPU_CORES=${{service.buildCores}} STACK_CORES=-j${{service.buildCores}}' # image: 'devfra.azurecr.io/de.fraport.trusted/ubuntu:22.04'
- task: CopyFiles@2 # endpoint: devfra
displayName: Prepare ${{service.name}} build artifacts for upload # steps:
inputs: # - script: |
Contents: '${{service.buildArtifacts}}' # id
TargetFolder: '$(Build.ArtifactStagingDirectory)' # docker build --help
- task: PublishBuildArtifacts@1 # sudo apt-get -y update
displayName: Publish ${{service.name}} build artifacts # sudo apt-get -y install buildah
inputs: # buildah bud -t fradrive-backend-test --volume .:/mnt/fradrive --file docker/backend/Dockerfile
PathtoPublish: '$(Build.ArtifactStagingDirectory)' # displayName: Build buildah image
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]}}

View File

@ -2,4 +2,4 @@
// //
// SPDX-License-Identifier: AGPL-3.0-or-later // 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 # 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-within: "_env:SYNCHRONISE_LDAP_WITHIN:1209600" # 14 Tage in Sekunden
synchronise-ldap-users-interval: "_env:SYNCHRONISE_LDAP_INTERVAL:3600" # jede Stunde 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-within: "_env:SYNCHRONISE_AVS_WITHIN:5702400" # alle 66 Tage
synchronise-avs-users-interval: "_env:SYNCHRONISE_AVS_INTERVAL:21600" # alle 6 Stunden 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-within: 172800
study-features-recache-relevance-interval: 293 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: log-settings:
detailed: "_env:DETAILED_LOGGING:false" detailed: "_env:DETAILED_LOGGING:false"
all: "_env:LOG_ALL:false" all: "_env:LOG_ALL:false"
@ -149,18 +146,22 @@ ldap:
ldap-re-test-failover: 60 ldap-re-test-failover: 60
lms-direct: lms-direct:
upload-header: "_env:LMSUPLOADHEADER:true" upload-header: "_env:LMSUPLOADHEADER:true"
upload-delimiter: "_env:LMSUPLOADDELIMITER:" upload-delimiter: "_env:LMSUPLOADDELIMITER:"
download-header: "_env:LMSDOWNLOADHEADER:true" download-header: "_env:LMSDOWNLOADHEADER:true"
download-delimiter: "_env:LMSDOWNLOADDELIMITER:," download-delimiter: "_env:LMSDOWNLOADDELIMITER:,"
download-cr-lf: "_env:LMSDOWNLOADCRLF:true" download-cr-lf: "_env:LMSDOWNLOADCRLF:true"
deletion-days: "_env:LMSDELETIONDAYS:7" orphan-deletion-days: "_env:LMSORPHANDELETIONDAYS:33"
orphan-deletion-batch: "_env:LMSORPHANDELETIONBATCH:12"
orphan-deletion-repeat-hours: "_env:LMSORPHANDELETIONREPEATHOURS:24"
avs: avs:
host: "_env:AVSHOST:skytest.fra.fraport.de" host: "_env:AVSHOST:skytest.fra.fraport.de"
port: "_env:AVSPORT:443" port: "_env:AVSPORT:443"
user: "_env:AVSUSER:fradrive" user: "_env:AVSUSER:fradrive"
pass: "_env:AVSPASS:" pass: "_env:AVSPASS:\"0000\""
timeout: "_env:AVSTIMEOUT:42"
cache-expiry: "_env:AVSCACHEEXPIRY:420"
lpr: lpr:
host: "_env:LPRHOST:fravm017173.fra.fraport.de" host: "_env:LPRHOST:fravm017173.fra.fraport.de"
@ -207,9 +208,6 @@ memcached:
timeout: "_env:MEMCACHED_TIMEOUT:20" timeout: "_env:MEMCACHED_TIMEOUT:20"
expiration: "_env:MEMCACHED_EXPIRATION:300" expiration: "_env:MEMCACHED_EXPIRATION:300"
memcache-auth: true memcache-auth: true
memcached-local:
maximum-ghost: 512
maximum-weight: 104857600 # 100MiB
upload-cache: upload-cache:
host: "_env:UPLOAD_S3_HOST:localhost" # should be optional, but all file transfers will be empty without an S3 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-favourites: 0
max-favourite-terms: 2 max-favourite-terms: 2
theme: Default theme: Default
date-time-format: "%d %b %y %R" date-time-format: "%d.%m.%Y %R"
date-format: "%d %b %Y" date-format: "%d.%m.%y"
time-format: "%R" time-format: "%R"
download-files: false download-files: false
warning-days: 1209600 warning-days: 1209600
@ -321,17 +319,6 @@ fallback-personalised-sheet-files-keys-expire: 2419200
download-token-expire: 604801 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: bot-mitigations:
- only-logged-in-table-sorting - only-logged-in-table-sorting
- unauthorized-form-honeypots - unauthorized-form-honeypots

View File

@ -1,38 +1,41 @@
ARG FROM_IMG=docker.io/library/haskell FROM docker.io/fpco/stack-build:lts-18.0
ARG FROM_TAG=8.10.4
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 # 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 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 && 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 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 \ # RUN apt-get -y update && apt-get -y install locales locales-all
--mount=type=cache,target=/var/lib/apt,sharing=locked \
apt-get -y update && apt-get install -y --no-install-recommends locales locales-all
# run-time dependencies for uniworx binary # run-time dependencies for uniworx binary
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ # RUN apt-get -y update && apt-get -y install fonts-roboto
--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 pdftk # RUN apt-get -y update && apt-get -y install pdftk
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ # RUN apt-get -y update && apt-get -y install texlive-base luatex
--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
# 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 ARG PROJECT_DIR=/fradrive
ENV PROJECT_DIR=${PROJECT_DIR}
RUN mkdir -p "${PROJECT_DIR}"; chmod -R 7777 "${PROJECT_DIR}" RUN mkdir -p "${PROJECT_DIR}"
WORKDIR ${PROJECT_DIR} RUN if [ "${PROJECT_DIR}" != "${MOUNT_DIR}" ] ; then cp -r "${MOUNT_DIR}"/* "${PROJECT_DIR}" ; fi
ENV HOME=${PROJECT_DIR}
RUN mkdir -p "${PROJECT_DIR}/.stack"
ENV STACK_ROOT="${PROJECT_DIR}/.stack" ENV STACK_ROOT="${PROJECT_DIR}/.stack"
RUN if [ ! -z "${IN_CI}" ]; then \ WORKDIR ${PROJECT_DIR}
stack install yesod-bin; \ ENV HOME=${PROJECT_DIR}
stack install hpack; \ RUN make -- --dependencies-backend STACK_ROOT=${STACK_ROOT} IN_CONTAINER=true JOB=${JOB}
fi
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 FROM debian:12.5
ARG FROM_TAG=12.5
FROM ${FROM_IMG}:${FROM_TAG} RUN apt-get -y update
# Setup locales # setup locales
# RUN apt-get update && apt-get -y install locales locales-all RUN apt-get -y install locales locales-all
# RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && \ RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && \
# locale-gen locale-gen
# ENV LANG=en_US.UTF-8 LANGUAGE=en_US:en LC_ALL=en_US.UTF-8 ENV LANG=en_US.UTF-8 LANGUAGE=en_US:en LC_ALL=en_US.UTF-8
# FraDrive runtime dependencies # FraDrive runtime dependencies
ENV DEBIAN_FRONTEND=noninteractive 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/lib/uniworx && chown -R uniworx:uniworx /var/lib/uniworx
RUN mkdir -p /var/log/uniworx && chown -R uniworx:uniworx /var/log/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 0750 /var/lib/uniworx
# RUN install -d -g uniworx -o uniworx -m 0755 /var/log/uniworx # RUN install -d -g uniworx -o uniworx -m 0755 /var/log/uniworx
COPY ./bin/uniworx /usr/bin/uniworx COPY ./bin/uniworx /usr/bin/uniworx
@ -42,6 +41,6 @@ COPY ./docker/fradrive/fradrive-entrypoint.sh /entrypoint.sh
RUN chmod 777 /entrypoint.sh RUN chmod 777 /entrypoint.sh
USER uniworx USER uniworx
ENTRYPOINT /entrypoint.sh ENTRYPOINT fradrive-entrypoint.sh
EXPOSE 8080/tcp EXPOSE 8080/tcp
VOLUME /var/lib/uniworx /var/log VOLUME /var/lib/uniworx /var/log

View File

@ -1,29 +1,32 @@
ARG FROM_IMG=docker.io/library/node FROM debian:12.5
ARG FROM_TAG=20
FROM ${FROM_IMG}:${FROM_TAG} # Basic dependencies
RUN apt-get -y update && apt-get -y install curl npm
ENV LANG=de_DE.UTF-8 # Build and watch dependencies
ENV LANGUAGE=de_DE.UTF-8
# build and watch dependencies
RUN apt-get -y update && apt-get -y install exiftool RUN apt-get -y update && apt-get -y install exiftool
RUN apt-get -y update && apt-get -y install imagemagick RUN apt-get -y update && apt-get -y install imagemagick
# test dependencies # Test dependencies
# RUN apt-get -y update && apt-get -y install chromium RUN apt-get -y update && apt-get -y install chromium
# ENV CHROME_BIN=chromium ENV CHROME_BIN=chromium
# configure npm to use given proxy if specified # TODO: use dotenv for npm version?
RUN if [ ! -z "${HTTP_PROXY}" ]; then npm config set proxy ${HTTP_PROXY}; fi RUN npm install -g n
RUN if [ ! -z "${FRAPORT_NOPROXY}" ]; then npm config set noproxy "${FRAPORT_NOPROXY}"; fi RUN n 20.17.0
ENV NODE_EXTRA_CA_CERTS="/etc/ssl/certs/ca-certificates.crt"
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 mkdir -p ${PROJECT_DIR}
RUN if [ "${PROJECT_DIR}" != "${MOUNT_DIR}" ] ; then cp -r ${MOUNT_DIR}/* ${PROJECT_DIR} ; fi
WORKDIR ${PROJECT_DIR} WORKDIR ${PROJECT_DIR}
ENV HOME=${PROJECT_DIR} ENV HOME=${PROJECT_DIR}
RUN if [ ! -z "${NPM_CUSTOM_REGISTRY}" ]; then \ #RUN make node_modules IN_CONTAINER=true
printf 'registry=${NPM_CUSTOM_REGISTRY}' > .npmrc \ #RUN make well-known IN_CONTAINER=true
; fi 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 { copy } from 'esbuild-plugin-copy';
// import manifestPlugin from 'esbuild-plugin-manifest'; // import manifestPlugin from 'esbuild-plugin-manifest';
import manifestPlugin from 'esbuild-plugin-assets-manifest'; import manifestPlugin from 'esbuild-plugin-assets-manifest';
// import copyWithHashPlugin from '@enonic/esbuild-plugin-copy-with-hash'; import copyWithHashPlugin from '@enonic/esbuild-plugin-copy-with-hash';
// import inlineImportPlugin from 'esbuild-plugin-inline-import'; import inlineImportPlugin from 'esbuild-plugin-inline-import';
import { nodeModulesPolyfillPlugin } from 'esbuild-plugins-node-modules-polyfill'; import { nodeModulesPolyfillPlugin } from 'esbuild-plugins-node-modules-polyfill';
const staticDir = './static'; const staticDir = './static';

View File

@ -5,7 +5,7 @@ import babelParser from "@babel/eslint-parser";
export default [ export default [
js.configs.recommended, js.configs.recommended,
{ {
files: ["frontend/src/**/*.js"], files: ["**/*.js"],
plugins: {}, plugins: {},
languageOptions: { languageOptions: {
ecmaVersion: 2018, 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: AGPL-3.0-or-later
// SPDX-License-Identifier: LicenseRef-Fraport-Corporate-Design // SPDX-License-Identifier: LicenseRef-Fraport-Corporate-Design
@import 'env';
$ico-width: 30px; $ico-width: 15px;
$icons: new, $icons: new,
ok, ok,
@ -35,6 +34,7 @@ $icons: new,
file-upload, file-upload,
file-zip, file-zip,
file-csv, file-csv,
file-missing,
sft-question, sft-question,
sft-hint, sft-hint,
sft-solution, sft-solution,
@ -95,15 +95,21 @@ $icons: new,
trash, trash,
reset-tries, reset-tries,
company, company,
company-warning,
edit, edit,
user-edit, user-edit,
placeholder, placeholder,
glasses,
user-badge,
user-unknown,
missing,
pin-protect,
loading; loading;
@each $name in $icons { @each $name in $icons {
.ico-#{$name} { .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-size: contain;
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: center; background-position: center;
@ -133,6 +139,7 @@ $icons: new,
.large-ico { .large-ico {
font-size: 2em; font-size: 2em;
min-width: 1em;
} }
.ico-spin { .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 // 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!'); if (!key) throw new Error('Cannot encrypt plaintext without a valid key!');
// TODO use const if possible // TODO use const if possible
// let plaintextB = Buffer.from(plaintext); let plaintextB = Buffer.from(plaintext);
// let cipherB = Buffer.alloc(plaintextB.length + sodium.crypto_secretbox_MACBYTES); let cipherB = Buffer.alloc(plaintextB.length + sodium.crypto_secretbox_MACBYTES);
// let nonceB = Buffer.alloc(sodium.crypto_secretbox_NONCEBYTES); let nonceB = undefined; // Buffer.alloc(sodium.crypto_secretbox_NONCEBYTES);
// let keyB = Buffer.from(key); let keyB = Buffer.from(key);
// sodium.crypto_secretbox_easy(cipherB, plaintextB, nonceB, keyB); // sodium.crypto_secretbox_easy(cipherB, plaintextB, nonceB, keyB);
const result = null; // cipherB; const result = cipherB;
console.log('encrypt result', result); console.log('encrypt result', result);
return result; return result;
} }
@ -519,10 +519,10 @@ function decrypt(ciphertext, key) {
if (!key) throw new Error('Cannot decrypt ciphertext without a valid key!'); if (!key) throw new Error('Cannot decrypt ciphertext without a valid key!');
// TODO use const if possible // TODO use const if possible
// let cipherB = Buffer.from(ciphertext); let cipherB = Buffer.from(ciphertext);
let plaintextB = null; // Buffer.alloc(cipherB.length - sodium.crypto_secretbox_MACBYTES); let plaintextB = undefined; Buffer.alloc(cipherB.length - sodium.crypto_secretbox_MACBYTES);
// let nonceB = undefined; Buffer.alloc(sodium.crypto_secretbox_NONCEBYTES); let nonceB = undefined; Buffer.alloc(sodium.crypto_secretbox_NONCEBYTES);
// let keyB = Buffer.from(key); let keyB = Buffer.from(key);
// sodium.crypto_secretbox_open_easy(plaintextB, cipherB, nonceB, keyB); // sodium.crypto_secretbox_open_easy(plaintextB, cipherB, nonceB, keyB);

View File

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

View File

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

View File

@ -96,7 +96,7 @@ sampleIntegral = sampleN scaleIntegral
instance PathPiece DiffTime where instance PathPiece DiffTime where
toPathPiece = (toPathPiece :: Pico -> Text) . MkFixed . diffTimeToPicoseconds toPathPiece = (toPathPiece :: Pico -> Text) . MkFixed . diffTimeToPicoseconds
fromPathPiece t = fromPathPiece t <&> \(MkFixed ps :: Pico) -> picosecondsToDiffTime ps fromPathPiece t = fromPathPiece t <&> \(MkFixed ps :: Pico) -> picosecondsToDiffTime ps
data LoadSimulation data LoadSimulation
= LoadSheetDownload = LoadSheetDownload
@ -214,13 +214,13 @@ runSimulation sim = do
delays <- replicateM (fromIntegral p) $ do delays <- replicateM (fromIntegral p) $ do
d <- view $ _2 . _simDelay d <- view $ _2 . _simDelay
sampleNDiffTime d sampleNDiffTime d
forConcurrently_ ([1..p] `zip` sort delays) $ \(n, d') -> do forConcurrently_ ([1..p] `zip` sort delays) $ \(n, d') -> do
begin <- liftIO getCurrentTime begin <- liftIO getCurrentTime
dur <- view $ _2 . _simDuration dur <- view $ _2 . _simDuration
tDuration <- sampleNDiffTime dur tDuration <- sampleNDiffTime dur
let MkFixed us = realToFrac d' :: Micro let MkFixed us = realToFrac d' :: Micro
threadDelay $ fromInteger us threadDelay $ fromInteger us
start <- liftIO getCurrentTime start <- liftIO getCurrentTime
@ -268,7 +268,7 @@ runSimulation' LoadSheetSubmission = do
-- Just formData <- return . getFormData FIDsubmission $ resp ^. responseBody -- Just formData <- return . getFormData FIDsubmission $ resp ^. responseBody
-- Just addButtonData <- return . flip (runFormScraper FIDsubmission) (resp ^. responseBody) $ do -- Just addButtonData <- return . flip (runFormScraper FIDsubmission) (resp ^. responseBody) $ do
-- let btnSel = "button" Scalpel.@: [Scalpel.hasClass "btn-mass-input-add"] -- let btnSel = "button" Scalpel.@: [Scalpel.hasClass "btn-mass-input-add"]
-- name <- Scalpel.attr "name" btnSel -- name <- Scalpel.attr "name" btnSel
-- value <- Scalpel.attr "value" btnSel -- value <- Scalpel.attr "value" btnSel
-- guard $ value == "add__0__0" -- guard $ value == "add__0__0"
@ -305,7 +305,7 @@ runSimulation' LoadSheetSubmission = do
procEnd <- join $ asks runtime procEnd <- join $ asks runtime
print ("proc", procEnd - procStart) print ("proc", procEnd - procStart)
resp3 <- liftIO . httpRetry $ Session.post session (uriToString id formURI mempty) subData resp3 <- liftIO . httpRetry $ Session.post session (uriToString id formURI mempty) subData
void . evaluate $! resp3 void . evaluate $! resp3
where where
@ -328,11 +328,11 @@ runSimulation' LoadSheetSubmission = do
-> m () -> m ()
logRetry shouldRetry err status = liftIO . putStrLn . pack $ Retry.defaultLogMsg shouldRetry err status logRetry shouldRetry err status = liftIO . putStrLn . pack $ Retry.defaultLogMsg shouldRetry err status
-- runSimulation' other = terror $ "Not implemented: " <> tshow other -- runSimulation' other = terror $ "Not implemented: " <> tshow other
runFormScraper :: FormIdentifier -> Scalpel.Scraper Lazy.ByteString a -> Lazy.ByteString -> Maybe a 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 fmap listToMaybe . Scalpel.chroots "form" $ do
fid' <- Scalpel.attr "value" $ "input" Scalpel.@: ["name" Scalpel.@= "form-identifier"] fid' <- Scalpel.attr "value" $ "input" Scalpel.@: ["name" Scalpel.@= "form-identifier"]
guard $ fid' == encodeUtf8 (fromStrict $ toPathPiece fid) 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 :: FormIdentifier -> Lazy.ByteString -> Maybe [FormParam]
getFormData = flip runFormScraper $ getFormData = flip runFormScraper $
Scalpel.chroots ("input") $ do Scalpel.chroots "input" $ do
name <- Scalpel.attr "name" Scalpel.anySelector name <- Scalpel.attr "name" Scalpel.anySelector
value <- Scalpel.attr "value" Scalpel.anySelector <|> pure "" value <- Scalpel.attr "value" Scalpel.anySelector <|> pure ""
return $ toStrict name := value return $ toStrict name := value
newLoadSession :: ReaderT SimulationContext IO Session newLoadSession :: ReaderT SimulationContext IO Session
newLoadSession = do newLoadSession = do
@ -354,7 +354,7 @@ newLoadSession = do
let withToken = case loadToken of let withToken = case loadToken of
Nothing -> id Nothing -> id
Just (Jwt bs) -> (:) (hAuthorization, "Bearer " <> bs) . filter ((/= hAuthorization) . fst) Just (Jwt bs) -> (:) (hAuthorization, "Bearer " <> bs) . filter ((/= hAuthorization) . fst)
liftIO . Session.newSessionControl (Just mempty) $ tlsManagerSettings liftIO . Session.newSessionControl (Just mempty) $ tlsManagerSettings
{ managerModifyRequest = \req -> return $ req { requestHeaders = withToken $ requestHeaders req } { 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 # SPDX-License-Identifier: AGPL-3.0-or-later
@ -67,6 +67,7 @@ BearerTokenExpiresTip: Wird der Ablaufzeitpunkt überschrieben und kein Ablaufze
BearerTokenOverrideStart: Startzeitpunkt BearerTokenOverrideStart: Startzeitpunkt
BearerTokenOverrideStartTip: Wird kein Startzeitpunkt angegeben, wird bei Verwendung des Tokens nur der Ablaufzeitpunkt überprüft. BearerTokenOverrideStartTip: Wird kein Startzeitpunkt angegeben, wird bei Verwendung des Tokens nur der Ablaufzeitpunkt überprüft.
HeadingAdminTokens: Tokens ausstellen HeadingAdminTokens: Tokens ausstellen
UserUnknown: Unbekannter Benutzer:in
#templates adminFeautures #templates adminFeautures
StudyFeaturesDegrees: Abschlüsse StudyFeaturesDegrees: Abschlüsse
@ -101,18 +102,20 @@ ProblemsHeadingDrivers: Fahrberechtigungen
ProblemsHeadingNotifications: Benachrichtigungen ProblemsHeadingNotifications: Benachrichtigungen
ProblemsHeadingMisc: Allgemein ProblemsHeadingMisc: Allgemein
ProblemsAvsProblem: Synchronisation mit AVS/MoBaKo komplett fehlgeschlagen 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 ProblemsDriverSynch0: Alle Sperrungen von Vorfeld-Fahrberechtigungen 'F' sind im AVS eingetragen
ProblemsDriverSynch1down: Alle Sperrungen von Rollfeld-Fahrberechtigungen 'R' 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 ProblemsDriverSynch1up: Alle gültigen Vorfeld-Fahrberechtigungen 'F' sind im AVS eingetragen
ProblemsDriverSynch2: Alle gültigen Rollfeld-Fahrberechtigungen 'R' 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 ProblemsRDriversHaveFs: Alle Inhaber einer Rollfeld-Fahrberechtigung besitzen auch eine gültige Vorfeld-Fahrberechtigung
ProblemsDriversHaveAvsIds: Alle Inhaber einer Fahrberechtigung konnten einer AVS Identifikationsnummer zugeordnet werden ProblemsDriversHaveAvsIds: Alle Inhaber einer Fahrberechtigung konnten einer AVS Identifikationsnummer zugeordnet werden
ProblemsUsersAreReachable: Für alle Benutzer ist eine E-Mail oder postalische Adresse bekannt 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 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 ProblemsNoBadAPCIds: Alle kürzlich empfangenen Druckauftragsbestätigungen waren gültig
ProblemsNoInsaneCompanySupervisions: Sind alle Firmen-bezogenen Ansprechpartnerbeziehungen zwischen passenden Firmenangehörigen?
ProblemsUnreachableHeading: Unerreichbare Benutzer ProblemsUnreachableHeading: Unerreichbare Benutzer
ProblemsUnreachableBody: Benutzer ohne E-Mail oder Postadresse, welche z.B. bei ablaufenden Berechtigungen nicht benachrichtigt werden können: 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 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: ProblemsRWithoutFBody: Diese Fahrer sind wegen einer ungültigen Vorfeld-Fahrberechtigung komplett gesperrt, obwohl eine gültige Rollfeld-Fahrberechtigung besteht:
ProblemsNoAvsIdHeading: Fahrer ohne AVS-Id ProblemsNoAvsIdHeading: Fahrer ohne AVS-Id
@ -120,6 +123,25 @@ ProblemsNoAvsIdBody: Fahrer mit gültiger Fahrberechtigung in FRADrive, welche t
ProblemsAvsSynchHeading: Synchronisation AVS Fahrberechtigungen ProblemsAvsSynchHeading: Synchronisation AVS Fahrberechtigungen
ProblemsAvsErrorHeading: Fehlermeldungen ProblemsAvsErrorHeading: Fehlermeldungen
ProblemsInterfaceSince: Berücksichtigt werden nur Erfolge und Fehler seit 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. InterfacesOk: Schnittstellen sind ok.
InterfacesFail n@Int: #{pluralDEeN n "Schnittstellenproblem"}! InterfacesFail n@Int: #{pluralDEeN n "Schnittstellenproblem"}!
@ -130,4 +152,13 @@ InterfaceSubtype: Betreffend
InterfaceWrite: Schreibend InterfaceWrite: Schreibend
InterfaceSuccess: Rückmeldung InterfaceSuccess: Rückmeldung
InterfaceInfo: Nachricht 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 # SPDX-License-Identifier: AGPL-3.0-or-later
@ -18,10 +18,10 @@ NoNameCandidatesInferred: No new name-mappings inferred
AllNameIncidencesDeleted: Successfully deleted all name observations AllNameIncidencesDeleted: Successfully deleted all name observations
AllParentIncidencesDeleted: Successfully deleted all parent-relation observations AllParentIncidencesDeleted: Successfully deleted all parent-relation observations
AllStandaloneIncidencesDeleted: Successfully deleted all standalone observations AllStandaloneIncidencesDeleted: Successfully deleted all standalone observations
IncidencesDeleted n: Successfully deleted #{show n} #{pluralEN n "observation" "observations"} IncidencesDeleted n: Successfully deleted #{pluralENsN n "observation"}
RedundantParentCandidatesRemoved n: Successfully removed #{n} rendundant #{pluralEN n "parent-candidate" "parent-candidates"} RedundantParentCandidatesRemoved n: Successfully removed #{n} rendundant #{pluralENs n "parent-candidate"}
RedundantStandaloneCandidatesRemoved n: Successfully removed #{n} rendundant #{pluralEN n "standalone-candidate" "standalone-candidates"} RedundantStandaloneCandidatesRemoved n: Successfully removed #{n} rendundant #{pluralENs n "standalone-candidate"}
ParentCandidatesInferred n: Successfully inferred #{n} field #{pluralEN n "parent-relation" "parent-reliations"} ParentCandidatesInferred n: Successfully inferred #{n} field #{pluralENs n "parent-relation"}
NoParentCandidatesInferred: No new parent-relations inferred NoParentCandidatesInferred: No new parent-relations inferred
StudyDegreeChangeSuccess: Successfully updated degrees StudyDegreeChangeSuccess: Successfully updated degrees
StudyTermsShort: Field shorthand StudyTermsShort: Field shorthand
@ -67,6 +67,7 @@ BearerTokenExpiresTip: If no expiration time is given, the token will not expire
BearerTokenOverrideStart: Start time BearerTokenOverrideStart: Start time
BearerTokenOverrideStartTip: If no start time is given, only the expiration time will be checked when the token is used. BearerTokenOverrideStartTip: If no start time is given, only the expiration time will be checked when the token is used.
HeadingAdminTokens: Issue tokens HeadingAdminTokens: Issue tokens
UserUnknown: User unknown
#templates adminfeatures #templates adminfeatures
StudyFeaturesDegrees: Degrees StudyFeaturesDegrees: Degrees
@ -101,7 +102,7 @@ ProblemsHeadingDrivers: Driving Licences
ProblemsHeadingNotifications: User communication ProblemsHeadingNotifications: User communication
ProblemsHeadingMisc: Miscellaneous ProblemsHeadingMisc: Miscellaneous
ProblemsAvsProblem: Synchronisation with AVS/MoBaKo failed entirely 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 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 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 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 ProblemsRDriversHaveFs: All driving licence 'R' holders also have a valid 'F' licence
ProblemsDriversHaveAvsIds: All driving licence holder could be matched with their AVS id ProblemsDriversHaveAvsIds: All driving licence holder could be matched with their AVS id
ProblemsUsersAreReachable: Either Email or postal address is known for all users 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 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 ProblemsUnreachableHeading: Unreachable Users
ProblemsUnreachableBody: Users without Email nor postal address, who thus cannot be notified about expiring qualifications: 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' 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: ProblemsRWithoutFBody: Drivers without apron driving licence are prohibited from driving, even if they own a valid maneuvering driving licence:
ProblemsNoAvsIdHeading: Drivers without AVS id 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: 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 ProblemsAvsSynchHeading: Synchronisation AVS Driving Licences
ProblemsAvsErrorHeading: Error Log 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. InterfacesOk: Interfaces are ok.
InterfacesFail n: #{pluralENsN n "interface problem"}! InterfacesFail n: #{pluralENsN n "interface problem"}!
@ -130,4 +152,13 @@ InterfaceSubtype: Affecting
InterfaceWrite: Write InterfaceWrite: Write
InterfaceSuccess: Returned InterfaceSuccess: Returned
InterfaceInfo: Message 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. UnauthorizedSchoolAdmin: You are no administrator for this department.
UnauthorizedAdminEscalation: You aren't an administrator for all departments for which this user is an administrator. 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. 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. 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. UnauthorizedSchoolExamOffice: You are not part of an exam office for this school.
UnauthorizedSystemExamOffice: You are not charged with system wide exam administration. UnauthorizedSystemExamOffice: You are not charged with system wide exam administration.
UnauthorizedSystemPrinter: You are not charged with system wide letter printing. 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. 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. UnauthorizedSchoolLecturer: You are no course administrator for this department.
UnauthorizedLecturer: You are no administrator for this course type. UnauthorizedLecturer: You are no administrator for this course category.
UnauthorizedCorrector: You are no sheet corrector for this course type. UnauthorizedCorrector: You are no sheet corrector for this course category.
UnauthorizedSheetCorrector: You are no corrector for this sheet. UnauthorizedSheetCorrector: You are no corrector for this sheet.
UnauthorizedExamCorrector: You are no corrector for this exam. UnauthorizedExamCorrector: You are no corrector for this exam.
UnauthorizedCorrectorAny: You are no corrector for any course type. UnauthorizedCorrectorAny: You are no corrector for any course category.
UnauthorizedRegistered: You are no participant in this course type. UnauthorizedRegistered: You are no participant in this course category.
UnauthorizedRegisteredExam: You are not registered for this exam. UnauthorizedRegisteredExam: You are not registered for this exam.
UnauthorizedRegisteredAnyExam: You are not registered for an exam. UnauthorizedRegisteredAnyExam: You are not registered for an exam.
UnauthorizedExamResult: You have no results in this exam. UnauthorizedExamResult: You have no results in this exam.
UnauthorizedExamOccurrenceRegistration: Registration for exam is not done including occurrence/room. UnauthorizedExamOccurrenceRegistration: Registration for exam is not done including occurrence/room.
UnauthorizedExternalExamResult: You have no results in this exam. UnauthorizedExternalExamResult: You have no results in this exam.
UnauthorizedParticipant: The specified user is no participant of this course type. UnauthorizedParticipant: The specified user is no participant of this course category.
UnauthorizedParticipantSelf: You are no participant of this course type. UnauthorizedParticipantSelf: You are no participant of this course category.
UnauthorizedCourseTime: This course type is not currently available. UnauthorizedCourseTime: This course category is not currently available.
UnauthorizedCourseRegistrationTime: This course type does not currently allow enrollment. UnauthorizedCourseRegistrationTime: This course category does not currently allow enrollment.
UnauthorizedSheetTime: This sheet is not currently available. 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. UnauthorizedTutorialTime: This course does not currently allow registration.
UnauthorizedCourseNewsTime: This news item is not currently available. UnauthorizedCourseNewsTime: This news item is not currently available.
UnauthorizedExamTime: This exam 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. UnauthorizedCorrectorSubmission: Correctors may not create submissions for this exercise sheet.
UnauthorizedCorrectionAnonymous: Correction is not anonymised. UnauthorizedCorrectionAnonymous: Correction is not anonymised.
DeprecatedRoute: This view is deprecated and will be removed. 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 UnauthorizedWrite: You do not have the write permission necessary to perform this action
UnauthorizedSystemMessageTime: This system-message is not currently available. UnauthorizedSystemMessageTime: This system-message is not currently available.
UnauthorizedSystemMessageAuth: This system-message is only available to logged in users. 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 WorkflowRoleNoSuchWorkflowWorkflow: The given workflow could not be found
WorkflowRoleNoPayload: This workflow does not contain any data 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 TutorialNoCapacity: Course has reached maximum capacity
ExamOccurrenceNoCapacity: Occurrence/Room has reached maximum capacity ExamOccurrenceNoCapacity: Occurrence/Room has reached maximum capacity
CourseNotEmpty: There are currently no participants enrolled for this course. 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 # SPDX-License-Identifier: AGPL-3.0-or-later
AvsPersonInfo: AVS Personendaten AvsPersonInfo: AVS Personendaten
AvsPersonId: AVS Personen Id AvsPersonId: AVS Personen Id
AvsPersonNo: AVS Personennummer 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 AvsCardNo: Ausweiskartennummer
AvsFirstName: Vorname AvsFirstName: Vorname
AvsLastName: Nachname AvsLastName: Nachname
AvsPrimaryCompany: Primäre Firma
AvsInternalPersonalNo: Personalnummer (nur Fraport AG) AvsInternalPersonalNo: Personalnummer (nur Fraport AG)
AvsVersionNo: Versionsnummer AvsVersionNo: Versionsnummer
AvsQueryNeeded: Benötigt Verbindung zum AVS.
AvsQueryEmpty: Bitte mindestens ein Anfragefeld ausfüllen! AvsQueryEmpty: Bitte mindestens ein Anfragefeld ausfüllen!
AvsQueryStatusInvalid t@Text: Nur numerische IDs eingeben, durch Komma getrennt! Erhalten: #{show t} AvsQueryStatusInvalid t@Text: Nur numerische IDs eingeben, durch Komma getrennt! Erhalten: #{show t}
AvsLicence: Fahrberechtigung 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 AvsTitleLicenceSynch: Abgleich Fahrberechtigungen zwischen AVS und FRADrive
BtnAvsRevokeUnknown: Fahrberechtigungen im AVS sofort entziehen BtnAvsRevokeUnknown: Fahrberechtigungen im AVS sofort entziehen
BtnAvsImportUnknown: AVS Daten unbekannter Personen importieren 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 RevokeUnknownLicencesOk: AVS Fahrberechtigungen unbekannter Fahrer wurden gesperrt
RevokeUnknownLicencesFail: Nicht alle AVS Fahrberechtigungen unbekannter Fahrer konnten entzogen werden, siehe Log für Details RevokeUnknownLicencesFail: Nicht alle AVS Fahrberechtigungen unbekannter Fahrer konnten entzogen werden, siehe Log für Details
AvsCommunicationError: AVS Schnittstelle lieferte einen unerwarteten Fehler. AvsCommunicationError: AVS Schnittstelle lieferte einen unerwarteten Fehler.
AvsCommunicationTimeout: AVS Schnittstelle antwortete nicht.
LicenceTableChangeAvs: Im AVS ändern LicenceTableChangeAvs: Im AVS ändern
LicenceTableGrantFDrive: In FRADrive erteilen LicenceTableGrantFDrive: In FRADrive erteilen
LicenceTableRevokeFDrive: In FRADrive entziehen LicenceTableRevokeFDrive: In FRADrive entziehen
TableAvsActiveCards: Gültige Ausweise TableAvsActiveCards: Gültige Ausweise
TableAvsCardValid: Aktuell gültig
TableAvsCardIssueDate: Ausgestellt am
TableAvsCardValidTo: Gültig bis
AvsCardAreas: Ausweiszusätze
AvsCardColor: Ausweisfarbe
AvsCardColorGreen: Grün AvsCardColorGreen: Grün
AvsCardColorBlue: Blau AvsCardColorBlue: Blau
AvsCardColorRed: Rot AvsCardColorRed: Rot
AvsCardColorYellow: Gelb AvsCardColorYellow: Gelb
LastAvsSynchronisation: Letzte AVS-Synchronisation LastAvsSynchronisation: Letzte AVS-Synchronisation
LastAvsSyncedBefore: Letzte AVS-Synchronisation vor
LastAvsSynchError: Letzte AVS-Fehlermeldung 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 # SPDX-License-Identifier: AGPL-3.0-or-later
AvsPersonInfo: AVS Person Info AvsPersonInfo: AVS person info
AvsPersonId: AVS Person Id AvsPersonId: AVS person id
AvsPersonNo: AVS Person Number 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 AvsCardNo: Card number
AvsFirstName: First name AvsFirstName: First name
AvsLastName: Last name AvsLastName: Last name
AvsPrimaryCompany: Primary company
AvsInternalPersonalNo: Personnel number (Fraport AG only) AvsInternalPersonalNo: Personnel number (Fraport AG only)
AvsVersionNo: Version number AvsVersionNo: Version number
AvsQueryNeeded: AVS connection required.
AvsQueryEmpty: At least one query field must be filled! AvsQueryEmpty: At least one query field must be filled!
AvsQueryStatusInvalid t: Numeric IDs only, comma seperated! #{show t} AvsQueryStatusInvalid t: Numeric IDs only, comma seperated! #{show t}
AvsLicence: Driving Licence 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 AvsTitleLicenceSynch: Synchronisation driving licences between AVS and FRADrive
BtnAvsRevokeUnknown: Revoke AVS driving licences for unknown persons immediately BtnAvsRevokeUnknown: Revoke AVS driving licences for unknown persons immediately
BtnAvsImportUnknown: Import AVS data for unknown persons 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 RevokeUnknownLicencesOk: AVS driving licences of unknown drivers revoked
RevokeUnknownLicencesFail: Not all AVS driving licences of unknown drivers could be revoked, see log for details RevokeUnknownLicencesFail: Not all AVS driving licences of unknown drivers could be revoked, see log for details
AvsCommunicationError: AVS interface returned an unexpected error. AvsCommunicationError: AVS interface returned an unexpected error.
AvsCommunicationTimeout: AVS interface returned no response within timeout limit.
LicenceTableChangeAvs: Change in AVS LicenceTableChangeAvs: Change in AVS
LicenceTableGrantFDrive: Grant in FRADrive LicenceTableGrantFDrive: Grant in FRADrive
LicenceTableRevokeFDrive: Revoke in FRADrive LicenceTableRevokeFDrive: Revoke in FRADrive
TableAvsActiveCards: Valid Cards TableAvsActiveCards: Valid Cards
TableAvsCardValid: Currently valid
TableAvsCardIssueDate: Issued
TableAvsCardValidTo: Valid to
AvsCardAreas: Card areas
AvsCardColor: Color
AvsCardColorGreen: Green AvsCardColorGreen: Green
AvsCardColorBlue: Blue AvsCardColorBlue: Blue
AvsCardColorRed: Red AvsCardColorRed: Red
AvsCardColorYellow: Yellow AvsCardColorYellow: Yellow
LastAvsSynchronisation: Last AVS synchronisation 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 CourseEditTitle: Kursart editieren/anlegen
CourseEditOk tid@TermId ssh@SchoolId csh@CourseShorthand: Kursart #{tid}-#{ssh}-#{csh} wurde erfolgreich geändert. 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. 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 CourseLecturer: Kursverwalter:in
MailSubjectParticipantInvitation tid@TermId ssh@SchoolId csh@CourseShorthand: [#{tid}-#{ssh}-#{csh}] Einladung zur Kursartteilnahme MailSubjectParticipantInvitation tid@TermId ssh@SchoolId csh@CourseShorthand: [#{tid}-#{ssh}-#{csh}] Einladung zur Kursartteilnahme
CourseParticipantInviteHeading courseName@Text: Einladung zum Kursartteilnahmer für #{courseName} 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! 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 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 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 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 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 CourseUserNoTutorialsDeregistered: Teilnehmer:in ist zu keinem der gewählten Kurse angemeldet
CourseUserTutorials: Angemeldete Kurse CourseUserTutorials: Angemeldete Kurse
CourseUserExams: Angemeldete Prüfungen CourseUserExams: Angemeldete Prüfungen
CourseUserExamOccurrences: Prüfungstermin
CourseUserExamOccurrenceOverride: Ggf. vorhandenen Prüfungstermin überschreiben
CourseUserExamOccurrenceAgainExaminer: Ggf. vorherige Prüfer erneut erlauben
CourseUserSheets: Übungsblätter CourseUserSheets: Übungsblätter
CsvColumnUserName: Voller Name des/der Teilnehmers/Teilnehmerin CsvColumnUserName: Voller Name des/der Teilnehmers/Teilnehmerin
CsvColumnUserMatriculation: AVS Nummer 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 CourseDate: Datum
MailSubjectLecturerInvitation tid@TermId ssh@SchoolId csh@CourseShorthand: [#{tid}-#{ssh}-#{csh}] Einladung als Kursverwalter:in 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 LecturerInvitationAccepted lType@Text csh@CourseShorthand: Sie wurden als #{lType} für #{csh} eingetragen
CourseExamRegistrationTime: Angemeldet seit CourseExamRegistrationTime: Angemeldet am
CourseParticipantStateIsActiveFilter: Ansicht CourseParticipantStateIsActiveFilter: Ansicht
CourseApply: Zur Kursart bewerben CourseApply: Zur Kursart bewerben
CourseAdministrator: Kursadministrator:in CourseAdministrator: Kursadministrator:in

View File

@ -2,7 +2,7 @@
# #
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
FilterCourse: Course FilterCourse: Course category
FilterCourseShort: Shorthand FilterCourseShort: Shorthand
FilterTerm: Year FilterTerm: Year
FilterCourseSchoolShort: Department FilterCourseSchoolShort: Department
@ -15,7 +15,7 @@ FilterCourseRegisterOpen: Enrolment is allowed
CourseRegistered: Enrolled CourseRegistered: Enrolled
CourseRegistration: Enrolment CourseRegistration: Enrolment
CourseDescription: Description CourseDescription: Description
CommCourseHeading: Course type message CommCourseHeading: Course category message
CourseLecturers: Course administrators CourseLecturers: Course administrators
CourseLecturerEmail: Email CourseLecturerEmail: Email
CourseLecturerAlreadyAdded: This user is already configured as a course administrator 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 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. 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 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 CourseSchool: Department
CourseSchoolMultipleTip: You may select from among multiple departments. Please ensure that you select the appropriate department for your course. CourseSchoolMultipleTip: You may select from among multiple departments. Please ensure that you select the appropriate department for your course.
CourseName: Title CourseName: Title
CourseShorthand: Shorthand 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 CourseSemester: Year
CourseDescriptionPlaceholder: Please include the module description CourseDescriptionPlaceholder: Please include the module description
CourseHomepageExternalPlaceholder: Optional external URL 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. 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 CourseVisibleFrom: Visible from
CourseVisibleTo: Visible to 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. 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 type from "Visible From" up to this date. When left empty visible courses will remain visible indefinitely. 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 type material is publicly accessible CourseMaterialFree: Course category material is publicly accessible
CourseFormSectionRegistration: Registration CourseFormSectionRegistration: Registration
CourseFormSectionAdministration: Administration CourseFormSectionAdministration: Administration
CourseCapacity: Capacity CourseCapacity: Capacity
CourseCapacityTip: Maximum permissable number of enrolments for this course; leave empty for unlimited 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 CourseSecretFormat: Arbitrary string
CourseSecretWrong: Wrong password CourseSecretWrong: Wrong password
CourseSecret: Access 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 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 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 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. 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 type should also be visible during the entire registration period (which is currently not the case). 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. NoSuchTerm tid: Year #{tid} does not exist.
NoSuchSchool ssh: Department #{ssh} does not exist. NoSuchSchool ssh: Department #{ssh} does not exist.
NoSuchCourseShorthand csh: There is no course type with shorthand #{csh}. NoSuchCourseShorthand csh: There is no course category with shorthand #{csh}.
NoSuchCourse: No such course type found. NoSuchCourse: No such course category 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. 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 CourseInvalidInput: Invalid input
CourseEditTitle: Edit/Create course CourseEditTitle: Edit/Create course
CourseEditOk tid ssh csh: Successfully edited course type #{tid}-#{ssh}-#{csh} CourseEditOk tid ssh csh: Successfully edited course category #{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. 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 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} CourseParticipantInviteHeading courseName: Invitation to enrol for #{courseName}
CourseParticipantInviteExplanation: You were invited to be a participant of a course. CourseParticipantInviteExplanation: You were invited to be a participant of a course.
CourseParticipantInviteField: Email addresses to invite CourseParticipantInviteField: Email addresses to invite
@ -79,21 +83,23 @@ CourseParticipantInvitationAccepted courseName: You were enrolled in #{courseNam
CourseParticipantEnlistDirectly: Enrol known users directly CourseParticipantEnlistDirectly: Enrol known users directly
CourseSubmissionGroup: Registered submission group CourseSubmissionGroup: Registered submission group
SubmissionGroupEmptyIsUnsetTip: Leave empty to remove users from their respective submission groups SubmissionGroupEmptyIsUnsetTip: Leave empty to remove users from their respective submission groups
CourseParticipantsRegisterHeading: Add course type participants CourseParticipantsRegisterHeading: Add course category participants
CourseParticipantsRegisterActionAddParticipants: Add course type participants CourseParticipantsRegisterActionAddParticipants: Add course category participants
CourseParticipantsRegisterActionAddTutorialMembers: Add course participants CourseParticipantsRegisterActionAddTutorialMembers: Add course participants
CourseParticipantsRegisterUsersField: Persons to register for course 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. 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 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! 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 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 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. 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 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 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 CourseParticipantsRegistered n: Successfully registered #{n} #{pluralEN n "participant" "participants"} for course
CourseParticipantsRegisteredTutorial 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 CourseRegistrationFilesNeedReupload: Registration files need to be reuploaded every time the registration is changed
CourseRegistrationFile: Registration file CourseRegistrationFile: Registration file
CourseRegistrationArchive: Zip archive of registration files 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. 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 type is only visible to enrolled participants and applicants. If you deregister now, you will not be able to access the course type again! 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 type now, you will not be able to re-register yourself. CourseDeregistrationNoReRegistration: If you deregister from the course category now, you will not be able to re-register yourself.
LoginNecessary: Please log in first! LoginNecessary: Please log in first!
RegisterRetry: You haven't been enrolled. Press "Enrol for course" to enrol RegisterRetry: You haven't been enrolled. Press "Enrol for course" to enrol
CourseRegisterOk: Successfully enrolled for course 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 CourseUserNoTutorialsDeregistered: Participant is not registered for any of the selected courses
CourseUserTutorials: Registered courses CourseUserTutorials: Registered courses
CourseUserExams: Registered exams CourseUserExams: Registered exams
CourseUserExamOccurrences: Exam occurrence
CourseUserExamOccurrenceOverride: Override other registrations for this exam, if any
CourseUserExamOccurrenceAgainExaminer: Possibly allow previous examiners again
CourseUserSheets: Exercise sheets CourseUserSheets: Exercise sheets
CsvColumnUserName: Participant's full name CsvColumnUserName: Participant's full name
CsvColumnUserMatriculation: Participant's AVS number CsvColumnUserMatriculation: Participant's AVS number
@ -144,7 +153,7 @@ CsvColumnUserExam: Exams which the user is registered for, separated by semicolo
CsvColumnUserSubmissionGroup: Registered submission group CsvColumnUserSubmissionGroup: Registered submission group
CsvColumnUserSurname: Participant's surname CsvColumnUserSurname: Participant's surname
CsvColumnUserFirstName: Participant's given name 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 CourseUserCsvName tid ssh csh: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase csh}-participants
CourseUserTutorial: Registered course CourseUserTutorial: Registered course
CourseUserExam: Registered exam CourseUserExam: Registered exam
@ -171,21 +180,21 @@ AssistantsFor: Assistants
CourseAdminFor: Course administration CourseAdminFor: Course administration
TutorsFor n: #{pluralENs n "Instructor" } TutorsFor n: #{pluralENs n "Instructor" }
CorrectorsFor n: #{pluralEN n "Corrector" "Correctors"} CorrectorsFor n: #{pluralEN n "Corrector" "Correctors"}
CourseParticipantsHeading: Course type participants CourseParticipantsHeading: Course category participants
CourseParticipantsCount n: #{n} CourseParticipantsCount n: #{n}
CourseParticipantsCountOf n m: #{n} of #{m} CourseParticipantsCountOf n m: #{n} of #{m}
CourseVisibility: Visibility 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 CourseRegistrationInterval: Enrolment
CourseDirectRegistrationInterval: Direct enrolment CourseDirectRegistrationInterval: Direct enrolment
CourseDeregisterUntil time: Deregistration only until #{time} CourseDeregisterUntil time: Deregistration only until #{time}
NotRegistered: Note enrolled for this course NotRegistered: Note enrolled for this course
CourseMaterial: Material CourseMaterial: Material
CourseMaterialNotFree: Course type material is only accessible to members of the course, e.g. for participants, instructors, correctors or administratiors. 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 type is available here CourseMaterialsFoundHere: Material for this course category 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) 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 type are available here CourseSheetsFoundHere: Exercise sheets for this course category 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) 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 SheetListCourse: Exercise sheets
CourseExams: Exams CourseExams: Exams
CourseTutorials: Courses CourseTutorials: Courses
@ -228,13 +237,13 @@ TutorialRegisterFrom: Register from
TutorialRegisterTo: Register to TutorialRegisterTo: Register to
CourseDeleteQuestion: Are you sure you want to delete the below-mentioned course? 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} UtilEditedBy name time: #{time} by #{name}
CourseDate: Date CourseDate: Date
MailSubjectLecturerInvitation tid ssh csh: [#{tid}-#{ssh}-#{csh}] Invitation to be a course administrator MailSubjectLecturerInvitation tid ssh csh: [#{tid}-#{ssh}-#{csh}] Invitation to be a course administrator
LecturerInvitationAccepted lType csh: You were registered as #{lType} for #{csh} LecturerInvitationAccepted lType csh: You were registered as #{lType} for #{csh}
CourseExamRegistrationTime: Registered since CourseExamRegistrationTime: Registered on
CourseParticipantStateIsActiveFilter: View CourseParticipantStateIsActiveFilter: View
CourseApply: Apply for course CourseApply: Apply for course
CourseAdministrator: Course administrator CourseAdministrator: Course administrator

View File

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

View File

@ -8,17 +8,17 @@ CourseEventTypePlaceholder: Lecture, Exercise discussion, ...
CourseEventTime: Time CourseEventTime: Time
CourseEventRoom: Regular room CourseEventRoom: Regular room
CourseEventRoomHidden: Room only for participants 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: — 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 CourseEventNote: Note
CourseEventActions: Actions CourseEventActions: Actions
CourseEventsActionEdit: Edit CourseEventsActionEdit: Edit
CourseEventsActionDelete: Delete CourseEventsActionDelete: Delete
CourseEventsActionCreate: New occurrence CourseEventsActionCreate: New occurrence
CourseEventCreated: Successfully created course type occurrence CourseEventCreated: Successfully created course category occurrence
CourseEventEdited: Successfully edited course type occurrence CourseEventEdited: Successfully edited course category occurrence
CourseEventDeleteQuestion: Are you sure you want to delete the course type occurrence mentioned below? CourseEventDeleteQuestion: Are you sure you want to delete the course category occurrence mentioned below?
CourseEventDeleted: Successfully deleted course type occurrence CourseEventDeleted: Successfully deleted course category occurrence
CourseEventEdit: Edit course type occurrence CourseEventEdit: Edit course category occurrence
CourseEventNew: New course type occurrence CourseEventNew: New course category occurrence

View File

@ -9,17 +9,17 @@ CourseNewsLastEdited time: Last changed: #{time}
CourseNewsActionEdit: Edit CourseNewsActionEdit: Edit
CourseNewsActionDelete: Delete CourseNewsActionDelete: Delete
CourseNewsActionCreate: Create new item 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 CourseNewsVisibleFromTip: If left empty this item is never visible. Leave empty for unfinished items
CourseNewsTitle: Title CourseNewsTitle: Title
CourseNewsSummary: Summary 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 CourseNewsContent: Content
CourseNewsParticipantsOnly: Only for course type participants CourseNewsParticipantsOnly: Only for course category participants
CourseNewsVisibleFrom: Visible from CourseNewsVisibleFrom: Visible from
CourseNewsCreated: Successfully created item of course type news CourseNewsCreated: Successfully created item of course category news
CourseNewsEdited: Successfully edited item of course type news CourseNewsEdited: Successfully edited item of course category news
CourseNewsDeleteQuestion: Are you sure you want to delete the item of course type news listed below? CourseNewsDeleteQuestion: Are you sure you want to delete the item of course category news listed below?
CourseNewsDeleted: Successfully deleted item of course type news CourseNewsDeleted: Successfully deleted item of course category news
CourseNewsNew: Add course type news CourseNewsNew: Add course category news
CourseNewsEdit: Edit item of course type 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 # SPDX-License-Identifier: AGPL-3.0-or-later
@ -35,7 +35,7 @@ ExamEditHeading examn@ExamName: #{examn} bearbeiten
ExamNameTip: Muss innerhalb der Veranstaltung eindeutig sein ExamNameTip: Muss innerhalb der Veranstaltung eindeutig sein
ExamDescription: Beschreibung ExamDescription: Beschreibung
ExamFormTimes: Zeiten ExamFormTimes: Zeiten
ExamFormOccurrences: Prüfungstermine/Räume ExamFormOccurrences: Prüfungstermine / Räume
ExamFormAutomaticFunctions: Automatische Funktionen ExamFormAutomaticFunctions: Automatische Funktionen
ExamFormCorrection: Korrektur ExamFormCorrection: Korrektur
ExamFormParts: Teile ExamFormParts: Teile
@ -43,12 +43,13 @@ ExamFormMode: Ausgestaltung der Prüfung
ExamFormGrades: Prüfungsleistungen ExamFormGrades: Prüfungsleistungen
ExamStart: Beginn ExamStart: Beginn
ExamEnd: Ende 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 ExamVisibleFrom: Sichtbar ab
ExamVisibleFromTip: Ohne Datum nie sichtbar und keine Anmeldung möglich ExamVisibleFromTip: Ohne Datum nie sichtbar und keine Anmeldung möglich
ExamRegisterFrom: Anmeldung ab ExamRegisterFrom: Anmeldung ab
ExamRegisterTo: Anmeldung bis 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 ExamDeregisterUntil: Abmeldung bis
ExamPublishOccurrenceAssignments: Termin- bzw. Raumzuteilung den Teilnehmer:innen mitteilen um 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 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 ExamBonus: Bonuspunkte-System
ExamGradingMode: Bewertungsmodus ExamGradingMode: Bewertungsmodus
ExamGradingModeTip: In welcher Form werden Prüfungsleistungen für diese Prüfung eingetragen? ExamGradingModeTip: In welcher Form werden Prüfungsleistungen für diese Prüfung eingetragen?
ExamStaff: Prüfer:innen/Verantwortliche Hochschullehrer:innen ExamStaff: Hauptverantworliche:r
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. ExamStaffTip: Hauptverantwortliche:r Prüfer:in, Textfeld zur reinen Information der Teilnehmenden.
ExamExamOfficeSchools: Zusätzliche Bereiche 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. 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 ExamCorrectorEmail: E-Mail
ExamCorrectors: Korrektor:innen ExamCorrectors: Prüfer: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. 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 Korrektor/eine Korrektorin mit dieser E-Mail ist bereits für diese Prüfung eingetragen ExamCorrectorAlreadyAdded: Ein Prüfer:innen mit dieser E-Mail ist bereits für diese Prüfung eingetragen
ExamParticipant: Prüfungsteilnehmer:in
ExamRoom: Raum ExamRoom: Raum
ExamRoomManual': Keine automatische bzw. selbstständige Zuteilung ExamRoomManual': Keine automatische bzw. selbstständige Zuteilung
ExamRoomSurname': Nach Nachname ExamRoomSurname': Nach Nachname
@ -86,6 +88,7 @@ ExamRoomAlreadyExists: Prüfung ist bereits eingetragen
ExamRoomName: Interne Bezeichnung ExamRoomName: Interne Bezeichnung
ExamRoomCapacity: Kapazität ExamRoomCapacity: Kapazität
ExamRoomCapacityNegative: Kapazität darf nicht negativ sein 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 ExamRoomTime: Termin
ExamRoomStart: Beginn ExamRoomStart: Beginn
ExamRoomEnd: Ende 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 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 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 ExamOccurrenceDuplicateName eoName@ExamOccurrenceName: Interne Terminbezeichnung #{eoName} kommt mehrfach vor
ExamOccurrenceExaminerIsUnset !ident-ok: —
ExamOccurrenceExaminerIsHidden: Prüfer wird nur Teilnehmer:innen angezeigt
ExamOccurrenceRoomIsUnset !ident-ok: — ExamOccurrenceRoomIsUnset !ident-ok: —
ExamOccurrenceRoomIsHidden: Raum wird nur Teilnehmer:innen angezeigt 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. 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 ExamRegisteredCount: Anmeldungen
ExamRegisteredCountOf num@Int64 count@Int64 !ident-ok: #{num}/#{count} ExamRegisteredCountOf num@Int64 count@Int64 !ident-ok: #{num}/#{count}
ExamOccurrences: Termine 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 GradingFrom: Ab
ExamNoShow: Nicht erschienen ExamNoShow: Nicht erschienen
ExamVoided: Entwertet 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 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 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 ExamRoomCapacityTip: Maximale Anzahl an Prüfungsteilnehmern für diesen Termin/Raum; leer lassen für unbeschränkte Teilnehmeranzahl
ExamRoomMappingRandom: Verteilung ExamRoomMappingRandom: Verteilung
ExamFinishHeading: Prüfungsergebnisse sichtbar schalten 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 # SPDX-License-Identifier: AGPL-3.0-or-later
ExamRegistrationInviteDeadline: Invitation valid until ExamRegistrationInviteDeadline: Invitation valid until
ExamRegistrationEnlistDirectly: Register known users directly 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. 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. ExamRegistrationRegisterCourseTip: Users that aren't enrolled already won't be registered for the exam otherwise.
ExamRegistrationInviteField: Email addresses ExamRegistrationInviteField: Email addresses
ExamParticipantsRegisterHeading: Add exam participants ExamParticipantsRegisterHeading: Add exam participants
@ -35,7 +35,7 @@ ExamEditHeading examn: Edit #{examn}
ExamNameTip: Needs to be unique within the course ExamNameTip: Needs to be unique within the course
ExamDescription: Description ExamDescription: Description
ExamFormTimes: Times ExamFormTimes: Times
ExamFormOccurrences: Occurrences/rooms ExamFormOccurrences: Occurrences / Rooms
ExamFormAutomaticFunctions: Automatic functions ExamFormAutomaticFunctions: Automatic functions
ExamFormCorrection: Correction ExamFormCorrection: Correction
ExamFormParts: Exam parts ExamFormParts: Exam parts
@ -43,12 +43,13 @@ ExamFormMode: Exam design
ExamFormGrades: Exam achievements ExamFormGrades: Exam achievements
ExamStart: Start ExamStart: Start
ExamEnd: End 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 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 ExamRegisterFrom: Register from
ExamRegisterTo: Register to 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 ExamDeregisterUntil: Deregister until
ExamPublishOccurrenceAssignments: Publish occurrence/room-assignments ExamPublishOccurrenceAssignments: Publish occurrence/room-assignments
ExamPublishOccurrenceAssignmentsTip: At this time participants can find out to which occurrence/room they are assigned 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 ExamBonus: Bonus point system
ExamGradingMode: Grading mode ExamGradingMode: Grading mode
ExamGradingModeTip: In which format should grades for this exam be entered? ExamGradingModeTip: In which format should grades for this exam be entered?
ExamStaff: Examiner/Responsible university teacher ExamStaff: Chief examiner
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. ExamStaffTip: Primary responsible examiner, arbirary text field for pure informational purposes.
ExamExamOfficeSchools: Additional departments 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. 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 ExamCorrectorEmail: Email
ExamCorrectors: Correctors ExamCorrectors: Examiner
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. 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: A corrector with this email address already exists ExamCorrectorAlreadyAdded: An examiner with this email address already exists
ExamParticipant: Examinee
ExamRoom: Room ExamRoom: Room
ExamRoomManual': No automatic or autonomous assignment ExamRoomManual': No automatic or autonomous assignment
ExamRoomSurname': By surname ExamRoomSurname': By surname
@ -86,6 +88,7 @@ ExamRoomAlreadyExists: Occurrence already configured
ExamRoomName: Internal name ExamRoomName: Internal name
ExamRoomCapacity: Capacity ExamRoomCapacity: Capacity
ExamRoomCapacityNegative: Capacity may not be negative ExamRoomCapacityNegative: Capacity may not be negative
ExamRoomCapacityInsufficient n@Int: Insufficient capacity, #{noneOneMoreEN n "none" "just one" ("only " <> tshow n)} remaining
ExamRoomTime: Time ExamRoomTime: Time
ExamRoomStart: Start ExamRoomStart: Start
ExamRoomEnd: End 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 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 ExamOccurrenceDuplicate eoRoom eoRange: Combination of room #{eoRoom} and occurrence #{eoRange} occurs multiple times
ExamOccurrenceDuplicateName eoName: Internal name #{eoName} 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: — 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. 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". 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". 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 CsvColumnExamUserBonus: Exam bonus points
CsvColumnExamUserParts: Number of points the participant achieved per exam part. One column per exam part if applicable. 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") 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) CsvColumnExamOfficeExamUserOccurrenceStart: Exam occurrence (ISO 8601)
CsvColumnUserStudyFeatures: All relevant features of study for the participant, separated by semicolon (;) 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 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. 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 ExamNoOccurrence: No occurrence/room
ExamBonusNone: No bonus points 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"} ExamUsersDeregistered count: Successfully deregistered #{show count} #{pluralEN count "participant" "participants"}
ExamUsersOccurrenceUpdated count: Successfully assigned occurrence/room for #{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"} ExamUsersResultsAccepted count: Successfully accepted computed result for #{show count} #{pluralEN count "participant" "participants"}
@ -217,6 +222,13 @@ ExamOccurrenceRuleParticipant: Occurrence/room assignment procedure
ExamRegisteredCount: Registrations ExamRegisteredCount: Registrations
ExamRegisteredCountOf num count: #{num}/#{count} ExamRegisteredCountOf num count: #{num}/#{count}
ExamOccurrences: Exams 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 GradingFrom: From
#templates widgets/bonus-rule #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. 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 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 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 ExamRoomCapacityTip: Maximum number of participants for this occurrence/room; leave empty for unlimited capacity
ExamRoomMappingRandom: Distribution ExamRoomMappingRandom: Distribution
ExamFinishHeading: Make results visible ExamFinishHeading: Make results visible
@ -302,9 +316,9 @@ ExamUserCsvOverrideResult: Override exam result in contradiction of computed val
ExamUserCsvSetBonus: Set bonus points ExamUserCsvSetBonus: Set bonus points
ExamUserCsvSetResult: Set exam result ExamUserCsvSetResult: Set exam result
ExamUserCsvSetPartResult: Set result for exam part ExamUserCsvSetPartResult: Set result for exam part
ExamUserCsvSetCourseNote: Modify course type participant notes ExamUserCsvSetCourseNote: Modify course category 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. 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 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. 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. 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. 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"). 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. UnauthorizedExternalExamCorrectorGrade: You may not enter overall exam achievements for this exam.
ExternalExamCorrectErrorMultipleMatchingUsers: This identifier matches on multiple students. ExternalExamCorrectErrorMultipleMatchingUsers: This identifier matches on multiple students.
ExternalExamCorrectErrorNoMatchingUsers: This identifier does not match any student. ExternalExamCorrectErrorNoMatchingUsers: This identifier does not match any student.
ExternalExamEdited coursen@CourseName examn@ExamName: Succesfully edited exam “#{examn}” 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 type “#{coursen}”. ExternalExamExists coursen@CourseName examn@ExamName: Exam “#{examn}” already exists for course category “#{coursen}”.
ExternalExamEdit coursen examn: Edit: #{coursen}, #{examn} ExternalExamEdit coursen examn: Edit: #{coursen}, #{examn}
ExternalExamSemester: Year ExternalExamSemester: Year
ExternalExamSchool: Department 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. ExternalExamStaffAlreadyAdded: Person is already associated with the exam.
ExternalExamStaffEmail: Email ExternalExamStaffEmail: Email
ExternalExamUserMustBeStaff: You yourself must always be an associated person for exams you create. 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 HeadingExternalExamList: External exams
HeadingExternalExamNew: New external exam 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}” MailSubjectExternalExamStaffInvitation coursen examn: Invitation to act as examiner for “#{examn}” of “#{coursen}”
ExternalExamOccurrenceEdited count: Successfully edited #{count} #{pluralEN count "occurrence" "occurrences"} ExternalExamOccurrenceEdited count: Successfully edited #{count} #{pluralEN count "occurrence" "occurrences"}
ExternalExamResultEdited count: Successfully edited #{count} #{pluralEN count "exam result" "exam results"} ExternalExamResultEdited count: Successfully edited #{count} #{pluralEN count "exam result" "exam results"}

View File

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

View File

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

View File

@ -2,16 +2,16 @@
# #
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
ParticipantsList: Lists of course type participants ParticipantsList: Lists of course category participants
ParticipantsIntersect: Common course type participants ParticipantsIntersect: Common course category participants
ParticipantsCsvName tid ssh: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-participants ParticipantsCsvName tid ssh: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-participants
ParticipantsIntersectCourseOption tid@TermId ssh@SchoolId coursen@CourseName: #{tid} - #{ssh} - #{coursen} ParticipantsIntersectCourseOption tid@TermId ssh@SchoolId coursen@CourseName: #{tid} - #{ssh} - #{coursen}
ParticipantsIntersectCourses: Courses 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. 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 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 ParticipantsIntersectNotOne: Intersection
AllUsersUnion: Union of all participants AllUsersUnion: Union of all participants
AllUsersIntersection: Intersection 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. CourseDeleteActiveParticipants: This course category 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. 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 SheetDeleted: Successfully deleted exercise sheet
SheetArchiveName tid ssh csh shn: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase csh}-#{foldedCase shn} 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} 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} 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 type #{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) 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 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 SheetActiveFrom: Active from/Submission period start
@ -24,7 +24,7 @@ SheetSolutionFromTip: Always invisible for participants if left empty; corrector
SheetName: Name SheetName: Name
SheetDescription: Description SheetDescription: Description
SheetRequireExam: Require registration for an exam? 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 SheetRequiredExam: Exam
SheetFormType: Valuation & submission SheetFormType: Valuation & submission
SheetFormTimes: Times SheetFormTimes: Times
@ -37,15 +37,15 @@ SheetMarkingFiles: Correction
SheetMarkingTip: Instructions for correction, visible only to correctors SheetMarkingTip: Instructions for correction, visible only to correctors
SheetPersonalisedFilesDownload: Download personalised sheet files SheetPersonalisedFilesDownload: Download personalised sheet files
SheetPersonalisedFiles: 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 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. 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 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. 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 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: 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. 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. 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 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" SheetErrHintEarly: "Hint from" must be after "Submission period start"
SheetErrSolutionEarly: "Solution from" must be after "Submission period end" 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 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 SheetWarnNoActiveTo: “Active to/Submission period end” should always be specified
CountTutProp: Courses count against proportion CountTutProp: Courses count against proportion
CountTutPropTip: If submissions are assigned by course, do those assignments count with regard to the set 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 IsRated: Marked
SheetTypeIsExam: Rating „as an exam part“ SheetTypeIsExam: Rating „as an exam part“
SheetGradingSummaryTitle intgr: #{intgr} #{pluralEN intgr "sheet" "sheets"} 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: PersonalisedSheetFilesIgnoredIntro: The following files were ignored:
PersonalisedSheetFilesDownloadRestrictByExamNone: No restriction PersonalisedSheetFilesDownloadRestrictByExamNone: No restriction
PersonalisedSheetFilesDownloadRestrictByExam: Restrict to exam participants PersonalisedSheetFilesDownloadRestrictByExam: Restrict to exam participants
PersonalisedSheetFilesDownloadRestrictByExamTip: Only download personalised sheet files for participants also registered to a certain exam? PersonalisedSheetFilesDownloadRestrictByExamTip: Only download personalised sheet files for participants also registered to a certain exam?
PersonalisedSheetFilesDownloadAnonymousField: Anonymisation 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 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 PersonalisedSheetFilesArchiveName tid ssh csh shn: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase csh}-#{foldedCase shn}-personalised_files
SheetGeneratePseudonym: Generate SheetGeneratePseudonym: Generate

View File

@ -49,10 +49,10 @@ SubmissionArchive: Zip-archive of submission files
SubmissionArchiveCorrected: Zip-archive of submission files including corrections SubmissionArchiveCorrected: Zip-archive of submission files including corrections
SubmissionFile: Submission file SubmissionFile: Submission file
SubmissionFiles: Submitted files 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. 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 type participant. 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 type participants for whom it could be determined, that you have already submitted with that person for this course. 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 type participants. MultiUserFieldExplanationCourseParticipants: This input searches through the addresses of all course category participants.
SubmissionAlreadyExistsFor email: #{email} already has a submission for this sheet. SubmissionAlreadyExistsFor email: #{email} already has a submission for this sheet.
SubmissionUsersEmpty: Submissions may not be created without submittors. SubmissionUsersEmpty: Submissions may not be created without submittors.
SubmissionUserAlreadyAdded: This user is already configured as a submittor 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. EMailUnknown email: Email #{email} does not belong to any known user.
CorDeficitProportion: Deficit (proportion) 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 CorrDownload: Download
SubmissionDownloadAnonymous: Anonymized SubmissionDownloadAnonymous: Anonymized
SubmissionDownloadSurnames: With surnames SubmissionDownloadSurnames: With surnames
@ -237,9 +237,9 @@ SubmissionFilterAuthorshipStatementCurrent: Current wording
SubmissionNoUsers: This submission has no associated users! SubmissionNoUsers: This submission has no associated users!
CsvColumnCorrectionTerm: Term of the course type of the submission CsvColumnCorrectionTerm: Term of the course category of the submission
CsvColumnCorrectionSchool: School of the course type of the submission CsvColumnCorrectionSchool: School of the course category of the submission
CsvColumnCorrectionCourse: Shorthand of the course type of the submission CsvColumnCorrectionCourse: Shorthand of the course category of the submission
CsvColumnCorrectionSheet: Name of the sheet of the submission CsvColumnCorrectionSheet: Name of the sheet of the submission
CsvColumnCorrectionSubmission: Number of the submission (uwa…) CsvColumnCorrectionSubmission: Number of the submission (uwa…)
CsvColumnCorrectionSurname: Submittor's surnames, separated by semicolon (;) 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 # SPDX-License-Identifier: AGPL-3.0-or-later
@ -36,6 +36,7 @@ TutorialDelete: Löschen
TutorialsHeading: Kurse TutorialsHeading: Kurse
TutorialNew: Neuer Kurs TutorialNew: Neuer Kurs
TutorialRegisteredSuccess tutn@TutorialName: Erfolgreich zum Kurs #{tutn} angemeldet 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 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} 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} TutorInviteHeading tutn@TutorialName: Einladung zum Ausbilder/zur Ausbilderin für #{tutn}
@ -49,4 +50,21 @@ TutorialUserGrantQualification: Qualifikation vergeben
TutorialUserRenewQualification: Qualifikation regulär verlängern 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 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 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 # SPDX-License-Identifier: AGPL-3.0-or-later
@ -12,16 +12,16 @@ TutorialEdited tutn: Successfully edited course #{tutn}
TutorialEditHeading tutn: Edit #{tutn} TutorialEditHeading tutn: Edit #{tutn}
TutorEmail: Email TutorEmail: Email
TutorialTutorAlreadyAdded: An user with this email address is already registered as instructor 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, ... TutorialTypePlaceholder: Tutorial, Driving lesson, ...
TutorialTypeTip: Only for informational purposes 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 TutorialRegGroup: Registration group
TutorialTutorControlled: Instructors may edit course 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? TutorialTutorControlledTip: Should instructors be allowed to edit arbitrary aspects of this course (name, registration group, room, time, other instructors, ...) at will?
TutorialCapacity: Capacity TutorialCapacity: Capacity
TutorialCapacityNonPositive: Capacity may not be negative 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? TutorialRoomHiddenTip: Should the room only be displayed to course participants?
RegisterFrom: Enrolment starts RegisterFrom: Enrolment starts
RegisterTo: Enrolment ends RegisterTo: Enrolment ends
@ -36,6 +36,7 @@ TutorialDelete: Delete
TutorialsHeading: Courses TutorialsHeading: Courses
TutorialNew: New course TutorialNew: New course
TutorialRegisteredSuccess tutn: Successfully registered for the course #{tutn} 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} TutorialDeregisteredSuccess tutn: Successfully de-registered for the course #{tutn}
MailSubjectTutorInvitation tid ssh csh tutn: [#{tid}-#{ssh}-#{csh}] Invitation to be a instructor for #{tutn} MailSubjectTutorInvitation tid ssh csh tutn: [#{tid}-#{ssh}-#{csh}] Invitation to be a instructor for #{tutn}
TutorInviteHeading tutn: Invitation to be instructor for #{tutn} TutorInviteHeading tutn: Invitation to be instructor for #{tutn}
@ -50,4 +51,21 @@ TutorialUserGrantQualification: Grant qualification
TutorialUserRenewQualification: Renew qualification TutorialUserRenewQualification: Renew qualification
TutorialUserRenewedQualification n@Int: Successfully renewed qualification #{tshow n} course #{pluralEN n "user" "users"} 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"} 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 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 # SPDX-License-Identifier: AGPL-3.0-or-later
@ -7,7 +7,6 @@ FirmSuperForeign: Firmenfremde Ansprechpartner
FirmSuperIrregular: Irreguläre Ansprechpartner FirmSuperIrregular: Irreguläre Ansprechpartner
FirmAssociates: Firmenangehörige FirmAssociates: Firmenangehörige
FirmContact: Firmenkontakt FirmContact: Firmenkontakt
FirmNoContact: Keine allgemeinen Kontaktinformationen bekannt.
FirmEmail: Allgemeine Email FirmEmail: Allgemeine Email
FirmAddress: Postanschrift FirmAddress: Postanschrift
FirmDefaultPreferenceInfo: Diese Voreinstellungen gelten nur für neue Firmenangehörige 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 FirmActNotify: Mitteilung versenden
FirmActResetSupervision: Ansprechpartner für alle Firmenangehörigen zurücksetzen FirmActResetSupervision: Ansprechpartner für alle Firmenangehörigen zurücksetzen
FirmActResetSuperKeep: Bisherige Ansprechpartner der Firmenangehörigen zusätzlich beibehalten? FirmActResetSuperKeep: Bisherige Ansprechpartner der Firmenangehörigen zusätzlich beibehalten?
FirmActRemoveSupers: Alle rein firmenbezogenen Ansprechpartnerbeziehungen für diese Personen entfernen?
FirmActResetMutualSupervision: Ansprechpartner beaufsichtigen sich gegenseitig FirmActResetMutualSupervision: Ansprechpartner beaufsichtigen sich gegenseitig
FirmActAddSupersvisors: Ansprechpartner hinzufügen FirmActResetSupersKeepAll: Alle behalten
FirmActAddSupersEmpty: Es konnten keine Ansprechpartner hinzugefügt werden 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. 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 FirmActChangeContactUser: Kontaktinformationen von allen Firmenangehörigen ändern
FirmActChangeContactFirm: Kontaktinformationen der Firma ändern FirmActChangeContactFirm: Kontaktinformationen der Firma ändern
FirmActChangeContactFirmInfo: Firmenkontaktinformationen werden nur für neue Firmenangehörige verwendet, für die sonst keine Kontaktinformationen vorliegen. 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 FirmUserActNotify: Mitteilung versenden
FirmUserActResetSupervision: Ansprechpartner auf Firmenstandard zurücksetzen FirmUserActResetSupervision: Ansprechpartner auf Firmenstandard zurücksetzen
FirmUserActSetSupervisor: Ansprechpartner ändern 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 FirmNewSupervisor: Neue individuelle Ansprechpartner hinzufügen
FirmSetSupervisor: Existierende 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)} 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)} FirmResetSupervision rem@Int64 set@Int64: #{tshow set} Ansprechpartner gesetzt#{bool mempty (", " <> tshow rem <> " zuvor gelöscht") (rem > 0)}
FirmSuperActNotify: Mitteilung versenden FirmSuperActNotify: Mitteilung versenden
FirmSuperActSwitchSuper: Standard Firmenansprechpartner abändern 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. 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 FirmSuperActRMSuperDef: Firmenansprechpartner entfernen
FirmSuperActRMSuperActive: Auch aktive Ansprechpartnerbeziehungen innerhalb dieser Firma beenden FirmSuperActRMSuperActive: Aktive Ansprechpartnerbeziehungen innerhalb dieser Firma beenden?
FirmsNotification: Firmen E-Mail versenden FirmsNotification: Firmen E-Mail versenden
FirmNotification fsh@CompanyShorthand: E-Mail an #{fsh} senden FirmNotification fsh@CompanyShorthand: E-Mail an #{fsh} senden
FirmsNotificationTitle: Firmen benachrichtigen FirmsNotificationTitle: Firmen benachrichtigen
@ -47,14 +59,39 @@ FilterSupervisor: Hat aktiven Ansprechpartner
FilterSupervisorCompany fsh@CompanyShorthand: Hat aktiven Ansprechpartner, #{fsh} der angehört FilterSupervisorCompany fsh@CompanyShorthand: Hat aktiven Ansprechpartner, #{fsh} der angehört
FilterSupervisorForeign fsh@CompanyShorthand: Hat aktiven Ansprechpartner, der selbst nicht #{fsh} angehört FilterSupervisorForeign fsh@CompanyShorthand: Hat aktiven Ansprechpartner, der selbst nicht #{fsh} angehört
FilterForeignSupervisor: Hat firmenfremde Ansprechpartner FilterForeignSupervisor: Hat firmenfremde Ansprechpartner
FilterIsForeignSupervisee: Ist Ansprechpartner für Firmenfremde
FilterFirmExtern: Externe Firma 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 FirmSupervisorOf fsh@CompanyShorthand: Ansprechpartner #{fsh} angehörig
FirmSupervisorIndependent: Ansprechpartner ohne jegliche Firmenzugehörigkeit FirmSupervisorIndependent: Ansprechpartner ohne jegliche Firmenzugehörigkeit
FirmEmployeeOf fsh@CompanyShorthand: Firmenangehörige #{fsh} FirmEmployeeOf fsh@CompanyShorthand: Firmenangehörige #{fsh}
NoCompanySelected: Bitte wählen Sie mindestens eine Firma aus. NoCompanySelected: Bitte wählen Sie mindestens eine Firma aus.
TableIsDefaultSupervisor: Standardansprechpartner TableIsDefaultSupervisor: Standardansprechpartner
TableSuperior: Vorgesetzter
TableIsDefaultReroute: Standardumleitung TableIsDefaultReroute: Standardumleitung
FormFieldPostal: Benachrichtigungseinstellung FormFieldPostal: Benachrichtigungseinstellung
FormFieldPostalTip: Gilt für alle Benachrichtigungen an diese Person, nicht nur für Umleitungen an diesen Ansprechpartner 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 FormFieldPinPass: Sensible PDF-E-Mail-Anhänge mit Passwort schützen?
FirmSupervisionKeyData: Kennzahlen Ansprechpartner 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 # SPDX-License-Identifier: AGPL-3.0-or-later
@ -7,7 +7,6 @@ FirmSuperForeign: External supervisor
FirmSuperIrregular: Irregular supervisor FirmSuperIrregular: Irregular supervisor
FirmAssociates: Company associated users FirmAssociates: Company associated users
FirmContact: Company Contact FirmContact: Company Contact
FirmNoContact: No general contact information known.
FirmEmail: General company email FirmEmail: General company email
FirmAddress: Postal address FirmAddress: Postal address
FirmDefaultPreferenceInfo: Default setting for new company associates only FirmDefaultPreferenceInfo: Default setting for new company associates only
@ -16,11 +15,18 @@ FirmActionInfo: Affects alle company associates under your supervision.
FirmActNotify: Send message FirmActNotify: Send message
FirmActResetSupervision: Reset supervisors for all company associates FirmActResetSupervision: Reset supervisors for all company associates
FirmActResetSuperKeep: Additionally keep existing supervisors of company associates? FirmActResetSuperKeep: Additionally keep existing supervisors of company associates?
FirmActRemoveSupers: Terminate all company related supervisionships?
FirmActResetMutualSupervision: Supervisors supervise each other FirmActResetMutualSupervision: Supervisors supervise each other
FirmActAddSupersvisors: Add supervisors FirmActResetSupersKeepAll: Keep all
FirmActAddSupersEmpty: No supervisors added 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. 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 FirmActChangeContactUser: Change contact data for all company associates
FirmActChangeContactFirm: Change company contact data 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. 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 FirmUserActNotify: Send message
FirmUserActResetSupervision: Reset supervisors to company default FirmUserActResetSupervision: Reset supervisors to company default
FirmUserActSetSupervisor: Change supervision 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 FirmNewSupervisor: Appoint new individual supervisors
FirmSetSupervisor: Add existing 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)} 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 FirmSuperActNotify: Send message
FirmSuperActSwitchSuper: Change default company supervisor 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 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 FirmsNotification: Send company notification e-mail
FirmNotification fsh: Send e-mail to #{fsh} FirmNotification fsh: Send e-mail to #{fsh}
FirmsNotificationTitle: Company notification FirmsNotificationTitle: Company notification
@ -47,14 +59,39 @@ FilterSupervisor: Has active supervisor
FilterSupervisorCompany fsh: Has active company supervisor belonging to #{fsh} FilterSupervisorCompany fsh: Has active company supervisor belonging to #{fsh}
FilterSupervisorForeign fsh: Has active supervisor not belonging to #{fsh} FilterSupervisorForeign fsh: Has active supervisor not belonging to #{fsh}
FilterForeignSupervisor: Has company-external supervisors FilterForeignSupervisor: Has company-external supervisors
FilterIsForeignSupervisee: Supervisor for company external users
FilterFirmExtern: External company 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} FirmSupervisorOf fsh@CompanyShorthand: Supervisors belonging to #{fsh}
FirmSupervisorIndependent: Independent supervisors FirmSupervisorIndependent: Independent supervisors
FirmEmployeeOf fsh@CompanyShorthand: #{fsh} associated users FirmEmployeeOf fsh@CompanyShorthand: #{fsh} associated users
NoCompanySelected: Select at least one company, please. NoCompanySelected: Select at least one company, please.
TableIsDefaultSupervisor: Default supervisor TableIsDefaultSupervisor: Default supervisor
TableSuperior: Superior
TableIsDefaultReroute: Default reroute TableIsDefaultReroute: Default reroute
FormFieldPostal: Notification type FormFieldPostal: Notification type
FormFieldPostalTip: Affects all notifications to this person, not just reroutes to this supervisor FormFieldPostalTip: Affects all notifications to this person, not just reroutes to this supervisor
FirmUserChanges n: Notification settings changed for #{n} company associates FormFieldPinPass: Protect sensitive PDF e-mail attachments by password?
FirmSupervisionKeyData: Supervision key data 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 InfoSupervisorTitle: Information for supervisors
InfoLecturerTitle: Information for course administrators InfoLecturerTitle: Information for course administrators
InfoLecturerCourses: Courses InfoLecturerCourses: Courses
InfoLecturerExercises: Course type exercises InfoLecturerExercises: Course category exercises
InfoLecturerTutorials: Courses InfoLecturerTutorials: Courses
InfoLecturerExams: Exams InfoLecturerExams: Exams
LecturerInfoTooltipNew: New feature LecturerInfoTooltipNew: New feature
@ -20,8 +20,8 @@ KnownBugs: Known bugs
ImplementationDetails: Implementation ImplementationDetails: Implementation
Clone: Cloning Clone: Cloning
Administrator: Administrator Administrator: Administrator
CommCourse: Course type message CommCourse: Course category message
Corrector: Corrector Corrector: Corrector
DefinitionCourseEvents: Course type occurrences DefinitionCourseEvents: Course category occurrences
DefinitionCourseNews: Course type news DefinitionCourseNews: Course category news
Invitations: Invitations 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! 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? PrintJobAcknowledgeQuestion n@Int d@Text: #{n} #{pluralDE n "Druckauftrag" "Druckaufräge"} vom #{d} als gedruckt und versendet bestätigen?
PrintJobAcknowledgements: Versanddatum von Briefen an PrintJobAcknowledgements: Versanddatum von Briefen an
PrintRecipient: Empfänger PrintRecipient: Empfänger:innen
PrintAffected: Betroffener
PrintSender !ident-ok: Sender PrintSender !ident-ok: Sender
PrintCourse: Kursarten PrintCourse: Kursarten
PrintQualification: Qualifikation PrintQualification: Qualifikation
@ -25,4 +26,7 @@ PrintPDF !ident-ok: PDF
PrintManualRenewal: Vorfeldführerschein Renewal-Brief testweise versenden PrintManualRenewal: Vorfeldführerschein Renewal-Brief testweise versenden
PrintLmsUser: ELearning Id PrintLmsUser: ELearning Id
PrintJobs: Druckaufräge 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? PrintJobAcknowledgeQuestion n d: Mark #{n} #{pluralENs n "print-job"} issued on #{d} as printed and mailed already?
PrintJobAcknowledgements: Sent-dates for Letter to PrintJobAcknowledgements: Sent-dates for Letter to
PrintRecipient: Recipient PrintRecipient: Recipient
PrintAffected: Affetcted
PrintSender: Sender PrintSender: Sender
PrintCourse: Course type PrintCourse: Course category
PrintQualification: Qualification PrintQualification: Qualification
PrintPDF: PDF PrintPDF: PDF
PrintManualRenewal: Manual sending of an apron driver's licence renewal letter PrintManualRenewal: Manual sending of an apron driver's licence renewal letter
PrintLmsUser: Elearning id PrintLmsUser: Elearning id
PrintJobs: Print jobs 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 # SPDX-License-Identifier: AGPL-3.0-or-later
@ -7,25 +7,36 @@ QualificationName: Qualifikation
QualificationDescription: Beschreibung QualificationDescription: Beschreibung
QualificationValidIndicator: Gültigkeit QualificationValidIndicator: Gültigkeit
QualificationValidDuration: Gültigkeitsdauer QualificationValidDuration: Gültigkeitsdauer
QualificationAuditDuration: Aufbewahrung Audit Log QualificationAuditDuration: Aufbewahrungszeitraum ELearning 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. 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 QualificationRefreshWithin: Erneurerungszeitraum
QualificationRefreshWithinTooltip: Optionaler Zeitraum vor Ablauf für automatischen Start des ELearnings und Versand einer Benachrichtigung per Brief oder Email. 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: 2. Erinnerung QualificationRefreshReminder: Zweite 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. 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? 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? 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 TableQualificationCountActive: Aktive
TableQualificationCountActiveTooltip: Anzahl Personen mit momentan gültiger Qualifikation TableQualificationCountActiveTooltip: Anzahl Personen mit momentan gültiger Qualifikation
TableQualificationCountTotal: Gesamt TableQualificationCountTotal: Gesamt
TableQualificationLmsReuses: LMS nutzt
TableQualificationLmsReusesTooltip: Diese Qualifikation hat kein eigenes ELearning, sondern wird über das ELearning der angegebenen Qualifikation abgewickelt.
TableQualificationIsAvsLicence: AVS TableQualificationIsAvsLicence: AVS
TableQualificationIsAvsLicenceTooltip: Unter welchem Namen wird diese Qualifikation mit dem Ausweisverwaltungssystem (AVS) synchronisiert? Betrifft nur Benutzer mit AVS PersonenID. TableQualificationIsAvsLicenceTooltip: Unter welchem Namen wird diese Qualifikation mit dem Ausweisverwaltungssystem (AVS) synchronisiert? Betrifft nur Benutzer mit AVS PersonenID.
TableQualificationSapExport: SAP TableQualificationSapExport: SAP
TableQualificationSapExportTooltip: Wird die Qualifikation an das SAP übermittelt? Betrifft nur Benutzer mit Fraport Personalnummer. TableQualificationSapExportTooltip: Wird die Qualifikation an das SAP übermittelt? Betrifft nur Benutzer mit Fraport Personalnummer.
LmsQualificationValidUntil: Gültig bis LmsQualificationValidUntil: Gültig bis
TableQualificationLastRefresh: Zuletzt erneuert 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 TableQualificationFirstHeld: Erstmalig
TableQualificationBlockedDue: Entzug TableQualificationBlockedDue: Entzug
TableQualificationBlockedTooltip: Wann wurde die Qualifikation vorübergehend außer Kraft gesetzt und warum wurde dies veranlasst? 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 LmsUser: Inhaber
LmsURL: Link ELearning LmsURL: Link ELearning
TableLmsEmail: EMail TableLmsEmail: EMail
TableLmsIdent: E-Learning Benutzer TableLmsIdent: ELearning Benutzer
TableLmsElearning: ELearning TableLmsElearning: ELearning
TableLmsElearningRenews: Automatische Verlängerung
TableLmsElearningLimit: Maximale Versuche
TableLmsPin: ELearning Passwort TableLmsPin: ELearning Passwort
TableLmsResetPin: E-Learning Passwort zurücksetzen? TableLmsResetPin: ELearning Passwort zurücksetzen?
TableLmsDatePin: E-Learning Passwort erstellt TableLmsDatePin: ELearning Passwort erstellt
TableLmsDate: Datum TableLmsDate: Datum
TableLmsDelete: Löschen? TableLmsDelete: Löschen?
TableLmsStaff: Interner Mitarbeiter? 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! 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 TableLmsEnded: Beendet
TableLmsStatus: Status ELearning 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 TableLmsStatusDay: Datum letzte Statusänderung ELearning
TableLmsSuccess: Bestanden TableLmsSuccess: Bestanden
TableLmsLock: Gesperrt TableLmsLock: Gesperrt
@ -70,6 +83,7 @@ LmsStatusExpired: Durchgefallen nach Fristablauf
LmsStatusSuccess: E#{nonBreakableDash}Learning bestanden LmsStatusSuccess: E#{nonBreakableDash}Learning bestanden
LmsStatusPlanned: E#{nonBreakableDash}Learning wird gerade noch eröffnet (nur für Admin sichtbar) 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. 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 FilterLmsValid: Aktuell gültig
FilterLmsRenewal: Erneuerung anstehend FilterLmsRenewal: Erneuerung anstehend
FilterLmsNotified: Benachrichtigt FilterLmsNotified: Benachrichtigt
@ -88,7 +102,8 @@ LmsReportInsert: Neues LMS Ereignis
LmsReportUpdate: LMS Ereignis Aktualisierung LmsReportUpdate: LMS Ereignis Aktualisierung
LmsReportCsvExceptionDuplicatedKey: CSV-Import LmsReport fand uneindeutigen Schlüssel LmsReportCsvExceptionDuplicatedKey: CSV-Import LmsReport fand uneindeutigen Schlüssel
LmsDirectUpload: Direkter Upload für automatisierte Systeme 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 MailSubjectQualificationRenewal qname@Text: Qualifikation #{qname} muss demnächst erneuert werden
MailSubjectQualificationExpiry qname@Text: Qualifikation #{qname} läuft demnächst ab MailSubjectQualificationExpiry qname@Text: Qualifikation #{qname} läuft demnächst ab
MailSubjectQualificationExpired qname@Text: Qualifikation #{qname} ist ab sofort ungültig MailSubjectQualificationExpired qname@Text: Qualifikation #{qname} ist ab sofort ungültig
@ -105,24 +120,30 @@ QualificationActBlock: Entziehen
QualificationActUnblock: Entzug aufheben QualificationActUnblock: Entzug aufheben
QualificationActRenew: Qualifikation regulär verlängern QualificationActRenew: Qualifikation regulär verlängern
QualificationActGrant: Qualifikation vergeben 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 QualificationStatusBlock l@QualificationShorthand n@Int m@Int: #{n}/#{m} #{l} entzogen
QualificationStatusUnblock l@QualificationShorthand n@Int m@Int: #{n}/#{m} #{l} reaktiviert QualificationStatusUnblock l@QualificationShorthand n@Int m@Int: #{n}/#{m} #{l} reaktiviert
LmsInactive: Aktuell kein ELearning aktiv 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. 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 LmsRenewalReminder: Erinnerung
LmsActNotify: Benachrichtigung ELearning erneut per Post oder E-Mail versenden LmsActNotify: Benachrichtigung ELearning erneut per Post oder E-Mail versenden
LmsActRenewPin: Neues zufällige ELearning Passwort zuweisen LmsActRenewNotify: Neues zufälliges ELearning Passwort zuweisen und Benachrichtigung per Post oder E-Mail versenden
LmsActRenewNotify: Neue zufällige ELearning Passwort zuweisen und Benachrichtigung per Post oder E-Mail versenden
LmsActReset: ELearning Fehlversuche zurücksetzen und entsperren 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. 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. LmsActResetFeedback n@Int m@Int: Für #{n}/#{m} ELearning Nutzer wurden alle Fehlversuche zurückgesetzt.
LmsActRestart: ELearning komplett neu starten 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. 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 LmsActRestartExtend: Gültig bis ggf. erhöhen für die nächsten # Tage
LmsActRestartUnblock: Entzug ggf. aufheben 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 LmsStateOpen: ELearning offen
LmsStatusLocked: ELearning gesperrt, wird ggf. bald geöffnet LmsStatusLocked: ELearning gesperrt, wird ggf. bald geöffnet
LmsStatusUnlocked: ELearning offen, wird ggf. bald gesperrt 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 LmsStarted: ELearning eröffnet
BtnLmsEnqueue: Nutzer mit ablaufenden Qualifikationen zum ELearning anmelden und benachrichtigen BtnLmsEnqueue: Nutzer mit ablaufenden Qualifikationen zum ELearning anmelden und benachrichtigen
BtnLmsDequeue: Nutzer mit beendetem ELearning aufräumen und ggf. 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 # SPDX-License-Identifier: AGPL-3.0-or-later
@ -8,24 +8,35 @@ QualificationDescription: Description
QualificationValidIndicator: Validity QualificationValidIndicator: Validity
QualificationValidDuration: Validity period QualificationValidDuration: Validity period
QualificationAuditDuration: Audit log retention 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 QualificationRefreshWithin: Refresh within
QualificationRefreshWithinTooltip: Optional period before expiry to start elearning and send a notification by post or email. 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: 2. Reminder QualificationRefreshReminder: Second 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. 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? QualificationElearningStart: Is elearning automatically started?
QualificationExpiryNotification: Invalidity notification? QualificationElearningRenew: Does successful elearning automatically extend a qualification by the default validity period?
QualificationExpiryNotificationTooltip: Qualification holder are notfied upon invalidity, provided they have activated such notification in their user settings. 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 TableQualificationCountActive: Active
TableQualificationCountActiveTooltip: Number of currently valid qualification holders TableQualificationCountActiveTooltip: Number of currently valid qualification holders
TableQualificationCountTotal: Total 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 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. 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 TableQualificationSapExport: Sent to SAP
TableQualificationSapExportTooltip: Is this qualification transmitted to SAP? Only applies to qualification holder having a Fraport AG personnel number. TableQualificationSapExportTooltip: Is this qualification transmitted to SAP? Only applies to qualification holder having a Fraport AG personnel number.
LmsQualificationValidUntil: Valid until LmsQualificationValidUntil: Valid until
TableQualificationLastRefresh: Last renewed 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 TableQualificationFirstHeld: First held
TableQualificationBlockedDue: Revocations TableQualificationBlockedDue: Revocations
TableQualificationBlockedTooltip: Why and when was this qualification temporarily suspended? TableQualificationBlockedTooltip: Why and when was this qualification temporarily suspended?
@ -49,6 +60,8 @@ TableLmsEmail: Email
TableLmsIdent: Elearning user TableLmsIdent: Elearning user
TableLmsPin: Elearning password TableLmsPin: Elearning password
TableLmsElearning: Elearning TableLmsElearning: Elearning
TableLmsElearningRenews: Automatic renewal
TableLmsElearningLimit: Max attempts
TableLmsResetPin: Reset Elearning password? TableLmsResetPin: Reset Elearning password?
TableLmsDatePin: Elearning password created TableLmsDatePin: Elearning password created
TableLmsDate: Date TableLmsDate: Date
@ -57,10 +70,10 @@ TableLmsStaff: Staff?
TableLmsStarted: Started TableLmsStarted: Started
TableLmsReceived: Last update TableLmsReceived: Last update
TableLmsNotified: Notification sent 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 TableLmsEnded: Ended
TableLmsStatus: Status elearning 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 TableLmsStatusDay: Date of last elearning status change
TableLmsSuccess: Completed TableLmsSuccess: Completed
TableLmsLock: Locked TableLmsLock: Locked
@ -70,6 +83,7 @@ LmsStatusExpired: Failed due to expiry
LmsStatusSuccess: Passed LmsStatusSuccess: Passed
LmsStatusPlanned: E#{nonBreakableDash}learning is about to be opened soon (visible to Admins only) 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. LmsStatusDelay: Note that status changes may occassionaly require more than a hour to be displayed here.
FilterLmsLongValid: Long-term valid
FilterLmsValid: Currently valid FilterLmsValid: Currently valid
FilterLmsRenewal: Renewal due FilterLmsRenewal: Renewal due
FilterLmsNotified: Notified FilterLmsNotified: Notified
@ -88,7 +102,8 @@ LmsReportInsert: New LMS event
LmsReportUpdate: Update of LMS event LmsReportUpdate: Update of LMS event
LmsReportCsvExceptionDuplicatedKey: CSV Import LmsReport with ambiguous key LmsReportCsvExceptionDuplicatedKey: CSV Import LmsReport with ambiguous key
LmsDirectUpload: Direct upload for automated systems 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 MailSubjectQualificationRenewal qname: Qualification #{qname} must be renewed shortly
MailSubjectQualificationExpiry qname: Qualification #{qname} expires soon MailSubjectQualificationExpiry qname: Qualification #{qname} expires soon
MailSubjectQualificationExpired qname: Qualification #{qname} is no longer valid MailSubjectQualificationExpired qname: Qualification #{qname} is no longer valid
@ -105,15 +120,16 @@ QualificationActBlock: Revoke
QualificationActUnblock: Clear revocation QualificationActUnblock: Clear revocation
QualificationActRenew: Renew qualification QualificationActRenew: Renew qualification
QualificationActGrant: Grant 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 QualificationStatusBlock l n m: #{n}/#{m} #{l} revoked
QualificationStatusUnblock l n m: #{n}/#{m} #{l} reactivated QualificationStatusUnblock l n m: #{n}/#{m} #{l} reactivated
LmsInactive: Currently no active elearning 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. 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 LmsRenewalReminder: Reminder
LmsActNotify: Resend elearning notification by post or email 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 LmsActRenewNotify: Randomly replace elearning password and re-send notification by post or email
LmsActReset: Reset and unlock elearning 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. 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. 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 LmsActRestartExtend: Ensure validity for the next # days
LmsActRestartUnblock: Undo any revocations 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 LmsStateOpen: Elearning open
LmsStatusLocked: Elearning locked, may be opened soon LmsStatusLocked: Elearning locked, may be opened soon
LmsStatusUnlocked: Elearning still open, may be locked 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 LmsStarted: Elearning open since
BtnLmsEnqueue: Enqueue users with expiring qualifications for elearning and notify them BtnLmsEnqueue: Enqueue users with expiring qualifications for elearning and notify them
BtnLmsDequeue: Dequeue users with finished elearning and notify failed users 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 SchoolAuthorshipStatementSheetExamDefinition: Eigenständigkeitserklärung für prüfungszugehörige Übungsblattabgaben
SchoolAuthorshipStatementSheetExamDefinitionTip: Bitte in sowohl deutscher als auch englischer Sprache angeben. SchoolAuthorshipStatementSheetExamDefinitionTip: Bitte in sowohl deutscher als auch englischer Sprache angeben.
SchoolAuthorshipStatementSheetAllowOther: Abweichende Eigenständigkeitserklärungen für nicht-prüfungszugehörige Übungsblätter erlauben? 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 SchoolExists ssh: A department named „#{ssh}“ already exists
SchoolAdmin: Admin SchoolAdmin: Admin
SchoolLecturer: Lecturer SchoolLecturer: Lecturer
SchoolEvaluation: Course type evaluation SchoolEvaluation: Course category evaluation
SchoolExamOffice: Exam office SchoolExamOffice: Exam office
SchoolAuthorshipStatementSection: Statements of Authorship SchoolAuthorshipStatementSection: Statements of Authorship
@ -40,4 +40,6 @@ SchoolAuthorshipStatementSheetDefinitionTip: Please enter both german and englis
SchoolAuthorshipStatementSheetExamDefinition: Statement of Authorship for exam-related exercise sheets SchoolAuthorshipStatementSheetExamDefinition: Statement of Authorship for exam-related exercise sheets
SchoolAuthorshipStatementSheetExamDefinitionTip: Please enter both german and english statements. SchoolAuthorshipStatementSheetExamDefinitionTip: Please enter both german and english statements.
SchoolAuthorshipStatementSheetAllowOther: Allow adaptations for exam-unrelated exercise sheets? 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 #correctionsNotDistributed.hs + templates
MailSubjectSubmissionsUnassigned csh sheetName: Corrections for #{sheetName} of #{csh} could not be distributed 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 #courseRegistered.hs + templates
MailSubjectCourseRegistered csh: You were enrolled for #{csh} MailSubjectCourseRegistered csh: You were enrolled for #{csh}
MailSubjectCourseRegisteredOther displayName csh: #{displayName} was enrolled for #{csh} MailSubjectCourseRegisteredOther displayName csh: #{displayName} was enrolled for #{csh}
MailCourseRegisteredIntro courseName termDesc: You were 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 type “#{courseName}” (#{termDesc}). MailCourseRegisteredIntroOther displayName courseName termDesc: #{displayName} was enrolled for the course category “#{courseName}” (#{termDesc}).
#examActive.hs + templates #examActive.hs + templates
MailSubjectExamRegistrationActive csh examn: Registration is now allowed for #{examn} of #{csh} 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 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}). 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 MailSubjectExamDeregistrationSoonInactive csh examn: Deregistration for #{examn} in #{csh} ends shortly
@ -27,15 +27,15 @@ MailExamDeregistrationSoonInactiveIntro courseName termDesc examn: Soon you will
#examOffice.hs + templates #examOffice.hs + templates
MailSubjectExamOfficeExamResults coursen examn: Results for #{examn} of #{coursen} are now available 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 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} 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 #examOffice.hs + templates
MailSubjectExamResult csh examn: Results for #{examn} in #{csh} are now available 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 #sheetActive.hs + templates
MailSubjectSheetActive csh sheetName: #{sheetName} in #{csh} was released 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 #sheetInactive.hs + templates
MailSubjectSheetSoonInactive csh sheetName: The submission period for #{sheetName} of #{csh} ends shortly 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 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"}. 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 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"}. 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. 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. 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 AuthTagExamOffice: User is part of an exam office
AuthTagSystemExamOffice: User is charged with system wide exam administration AuthTagSystemExamOffice: User is charged with system wide exam administration
AuthTagSystemPrinter: User is responsible for system wide letter printing 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 AuthTagToken: User is presenting an authorisation-token
AuthTagNoEscalation: User permissions are not being expanded to other departments AuthTagNoEscalation: User permissions are not being expanded to other departments
AuthTagDeprecated: Page is not deprecated AuthTagDeprecated: Page is not deprecated
@ -26,7 +26,7 @@ AuthTagTutor: User is instructor
AuthTagTutorControl: Instructors have control over their course AuthTagTutorControl: Instructors have control over their course
AuthTagTime: Time restrictions are fulfilled AuthTagTime: Time restrictions are fulfilled
AuthTagStaffTime: Time restrictions for teaching staff 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 AuthTagCourseRegistered: User is enrolled in course
AuthTagTutorialRegistered: User is course participant AuthTagTutorialRegistered: User is course participant
AuthTagExamRegistered: User is exam 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 AuthTagRegisterGroup: User is not participant in any course of the same registration group
AuthTagCapacity: Capacity is sufficient AuthTagCapacity: Capacity is sufficient
AuthTagEmpty: Resource is “empty” AuthTagEmpty: Resource is “empty”
AuthTagMaterials: Course type material is publicly accessable AuthTagMaterials: Course category material is publicly accessable
AuthTagOwner: User is owner AuthTagOwner: User is owner
AuthTagPersonalisedSheetFiles: User has been assigned personalised sheet files AuthTagPersonalisedSheetFiles: User has been assigned personalised sheet files
AuthTagRated: Submission is marked 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 AuthTagCorrectorSubmissions: Submissions are registered by correctors
AuthTagCorrectionAnonymous: Correction is anonymised AuthTagCorrectionAnonymous: Correction is anonymised
AuthTagSelf: User is only accessing their only data 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 WarningDays: Deadline-preview
WarningDaysTip: How many days ahead should deadlines regarding exams etc. be displayed on the homepage? WarningDaysTip: How many days ahead should deadlines regarding exams etc. be displayed on the homepage?
ShowSex: Show sex of other users 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 PDFPassword: Password to lock PDF email attachments
PDFPasswordTip: Please note that this password is displayed to FRADrive admins and is saved unencrypted 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 NotificationSettings: Desired notifications
NotificationTriggerKindAll: For all users NotificationTriggerKindAll: For all users
NotificationTriggerKindCourseParticipant: For course type participants NotificationTriggerKindCourseParticipant: For course category participants
NotificationTriggerKindExamParticipant: For exam participants NotificationTriggerKindExamParticipant: For exam participants
NotificationTriggerKindCorrector: For correctors NotificationTriggerKindCorrector: For correctors
NotificationTriggerKindLecturer: For course administrators NotificationTriggerKindLecturer: For course administrators
NotificationTriggerKindCourseLecturer: For course administrators NotificationTriggerKindCourseLecturer: For course administrators
NotificationTriggerKindAdmin: For administrators NotificationTriggerKindAdmin: For administrators
NotificationTriggerKindExamOffice: For the exam office NotificationTriggerKindExamOffice: For the exam office
NotificationTriggerKindEvaluation: For course type evaluations NotificationTriggerKindEvaluation: For course category evaluations
NotificationTriggerKindSubmissionUser: For participants in an exercise sheet submission NotificationTriggerKindSubmissionUser: For participants in an exercise sheet submission
NotificationTriggerSubmissionRatedGraded: My submission for an exercise sheet was marked (not purely informational) 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 # SPDX-License-Identifier: AGPL-3.0-or-later
@ -19,19 +19,25 @@ ProfileSubmissionGroups: Abgabegruppen
ProfileSubmissions: Abgaben ProfileSubmissions: Abgaben
ProfileRemark: Hinweis ProfileRemark: Hinweis
ProfileQualifications: Eigene Qualifikationen ProfileQualifications: Eigene Qualifikationen
ProfileEnrolledExams: Angemeldete Prüfungen
PersonalInfoExamAchievementsWip: Die Anzeige von Prüfungsergebnissen wird momentan an dieser Stelle leider noch nicht unterstützt. 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. 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. 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. 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. 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 ProfileCorrections: Auflistung aller zugewiesenen Korrekturen
Remarks: Hinweise Remarks: Hinweis:
ProfileSupervisor: Übergeordnete Ansprechpartner ProfileNoSupervisor: Keine übergeordneten Ansprechpartner vorhanden
ProfileSupervisee: Ist Ansprechpartner für 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 UserTelephone: Telefon
UserMobile: Mobiltelefon UserMobile: Mobiltelefon
Company: Firmenzugehörigkeit Company: Firmenzugehörigkeit
CompanyPersonalNumber: Personalnummer (nur Fraport AG) CompanyPersonalNumber: Personalnummer
CompanyPersonalNumberFraport: Personalnummer (nur Fraport AG)
CompanyDepartment: Abteilung 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 # SPDX-License-Identifier: AGPL-3.0-or-later
@ -11,7 +11,7 @@ LastLogin: Last login
NeverSet: Never NeverSet: Never
ProfileCorrector: Corrector ProfileCorrector: Corrector
ProfileCourses: Own courses ProfileCourses: Own courses
ProfileCourseParticipations: Course type registrations ProfileCourseParticipations: Course category registrations
ProfileCourseExamResults: Exam achievements ProfileCourseExamResults: Exam achievements
ProfileTutorials: Own courses ProfileTutorials: Own courses
ProfileTutorialParticipations: Courses ProfileTutorialParticipations: Courses
@ -19,19 +19,25 @@ ProfileSubmissionGroups: Submission groups
ProfileSubmissions: Submissions ProfileSubmissions: Submissions
ProfileRemark: Remarks ProfileRemark: Remarks
ProfileQualifications: Owned Qualifications ProfileQualifications: Owned Qualifications
ProfileEnrolledExams: Enrolled Exams
PersonalInfoExamAchievementsWip: The feature to display your exam achievements has not yet been implemented. 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. 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. 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. 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. 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 ProfileCorrections: List of all assigned corrections
Remarks: Remarks Remarks: Remark:
ProfileSupervisor: Supervised by ProfileNoSupervisor: Is not supervised by anynone
ProfileSupervisee: Supervises 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 UserTelephone: Phone
UserMobile: Mobile UserMobile: Mobile
Company: Company affilitaion Company: Company affiliation
CompanyPersonalNumber: Personnel number (Fraport AG only) CompanyPersonalNumber: Personnel number
CompanyPersonalNumberFraport: Personnel number (Fraport AG only)
CompanyDepartment: Department CompanyDepartment: Department

View File

@ -22,6 +22,7 @@ AdminUserPostAddress: Postalische Anschrift
AdminUserPrefersPostal: Briefe anstatt Email bevorzugt AdminUserPrefersPostal: Briefe anstatt Email bevorzugt
AdminUserPinPassword: Passwort zur Verschlüsselung von PDF Anhängen in Emails AdminUserPinPassword: Passwort zur Verschlüsselung von PDF Anhängen in Emails
AdminUserNoPassword: Kein Passwort gesetzt 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 AdminUserAssimilate: Diesen Benutzer assimilieren von
UserAdded: Benutzer erfolgreich angelegt UserAdded: Benutzer erfolgreich angelegt
UserCollision: Benutzer konnte wegen Eindeutigkeit nicht angelegt werden 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 AuthPWHashConfigured: Nutzer:in meldet sich nun mit FRADrive spezifischer Kennung an
UsersCourseSchool: Bereich UsersCourseSchool: Bereich
ActionNoUsersSelected: Keine Benutzer:innen ausgewählt ActionNoUsersSelected: Keine Benutzer:innen ausgewählt
SynchroniseAvsUserQueued n@Int: AVS-Synchronisation von #{n} #{pluralDE n "Benutzer:in" "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!
SynchroniseLdapUserQueued n@Int: LDAP-Synchronisation von #{n} #{pluralDE n "Benutzer:in" "Benutzer:innen"} angestoßen 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!
SynchroniseLdapAllUsersQueued: LDAP-Synchronisation von allen Benutzer:innen angestoßen 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 UserListTitle: Komprehensive Benutzerliste
UserRecipientsTitle name@Text: Benachrichtigungsempfänger für #{name}
AccessRightsSaved: Berechtigungen erfolgreich verändert AccessRightsSaved: Berechtigungen erfolgreich verändert
AccessRightsNotChanged: Berechtigungen wurden nicht verändert AccessRightsNotChanged: Berechtigungen wurden nicht verändert
AuthLDAPLookupFailed: Nutzer:in konnte aufgrund eines LDAP-Fehlers nicht nachgeschlagen werden 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! 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 UserAvsSync: AVS-Synchronisieren
UserLdapSync: LDAP-Synchronisieren UserLdapSync: LDAP-Synchronisieren
AllUsersLdapSync: Alle LDAP-Synchronisieren
UserHijack: Sitzung übernehmen UserHijack: Sitzung übernehmen
UserAddSupervisor: Ansprechpartner hinzufügen UserAddSupervisor: Ansprechpartner hinzufügen
UserSetSupervisor: Ansprechpartner ersetzen UserSetSupervisor: Ansprechpartner ersetzen
UserRemoveSupervisor: Alle Ansprechpartner entfernen UserRemoveSupervisor: Alle Ansprechpartner entfernen
UserRemoveClients: Alle Ansprechpartnerbeziehungen zu Klienten beenden
UserIsSupervisor: Ist Ansprechpartner 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 AuthKindLDAP: Fraport AG Kennung
AuthKindPWHash: FRADrive Kennung AuthKindPWHash: FRADrive Kennung
AuthKindNoLogin: Kein Login möglich 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. 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! 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. 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 AdminUserPrefersPostal: Prefers postal letters over email
AdminUserPinPassword: Password used for PDF attachments to emails AdminUserPinPassword: Password used for PDF attachments to emails
AdminUserNoPassword: No password set 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 AdminUserAssimilate: Assimilate user by another user
UserAdded: Successfully added user UserAdded: Successfully added user
UserCollision: Could not create user due to uniqueness constraint 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 AuthPWHashConfigured: User now logs in using their FRADrive specific account
UsersCourseSchool: Department UsersCourseSchool: Department
ActionNoUsersSelected: No users selected ActionNoUsersSelected: No users selected
SynchroniseAvsUserQueued n: Triggered AVS synchronisation of #{n} #{pluralEN n "user" "users"}. SynchroniseAvsUserQueued n: Triggered forced AVS synchronisation of #{n} #{pluralEN n "user" "users"}, which may take several minutes to complete.
SynchroniseLdapUserQueued n: Triggered LDAP synchronisation of #{n} #{pluralEN n "user" "users"}. 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.
SynchroniseLdapAllUsersQueued: Triggered LDAP synchronisation of all users 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 UserListTitle: Comprehensive list of users
UserRecipientsTitle name: Notificationrecipients for #{name}
AccessRightsSaved: Successfully updated permissions AccessRightsSaved: Successfully updated permissions
AccessRightsNotChanged: Permissions left unchanged AccessRightsNotChanged: Permissions left unchanged
AuthLDAPLookupFailed: User could not be looked up due to a LDAP error 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! UserAccountDeleteWarning: Caution, this permanently deletes users and all of their associated data. Exam results must be stored long term!
UserAvsSync: Synchronise with AVS UserAvsSync: Synchronise with AVS
UserLdapSync: Synchronise with LDAP UserLdapSync: Synchronise with LDAP
AllUsersLdapSync: Synchronise all with LDAP
UserHijack: Hijack session UserHijack: Hijack session
UserAddSupervisor: Add supervisor UserAddSupervisor: Add supervisor
UserSetSupervisor: Replace supervisors UserSetSupervisor: Replace supervisors
UserRemoveSupervisor: Set to unsupervised UserRemoveSupervisor: Set to unsupervised
UserRemoveClients: Remove all clients
UserIsSupervisor: Is supervisor 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 AuthKindLDAP: Fraport AG account
AuthKindPWHash: FRADrive account AuthKindPWHash: FRADrive account
AuthKindNoLogin: No login AuthKindNoLogin: No login
Name: Name Name: Name
UsersChangeSupervisorsSuccess usr spr: #{pluralENsN spr "supervisor"} for #{pluralENsN usr "user"} set. 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! 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 #messages or constructors that are used all over the code
Logo !ident-ok: Uni2work Logo !ident-ok: FRADrive
EmailInvitationWarning: Diese Adresse konnte keinem Uni2work-Benutzer/keiner Uni2work-Benutzerin zugeordnet werden. Es wird eine Einladung per E-Mail versandt. 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: — BoolIrrelevant !ident-ok: —
FieldPrimary: Hauptfach FieldPrimary: Hauptfach
FieldSecondary: Nebenfach FieldSecondary: Nebenfach
MultiEmailFieldTip: Es sind mehrere, Komma-separierte, E-Mail-Adressen möglich MultiEmailFieldTip: Es sind mehrere, Komma-separierte, E-Mail-Adressen möglich
MultiSelectTip: Mehrfachauswahl und Abwählen mit Strg-Klick MultiSelectTip: Mehrfachauswahl und Abwählen mit Strg-Klick
WeekDay: Wochentag WeekDay: Wochentag
LdapIdentificationOrEmail: Fraport AG-Kennung / E-Mail-Adresse Hours: Stunden
SomeMonths: Monate
SomeDays: Tage
Months num@Int64: #{num} #{pluralDE num "Monat" "Monate"} Months num@Int64: #{num} #{pluralDE num "Monat" "Monate"}
Days num@Int64: #{num} #{pluralDE num "Tag" "Tage"} 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 ClusterVolatileQuickActionsEnabled: Schnellzugriffsmenü aktiv
AvsNoLicence: Keine Fahrberechtigung AvsNoLicence: Keine Fahrberechtigung
AvsLicenceVorfeld: Vorfeld Fahrberechtigung AvsLicenceVorfeld: Vorfeld Fahrberechtigung
AvsLicenceRollfeld: Rollfeld Fahrberechtigung AvsLicenceRollfeld: Rollfeld Fahrberechtigung
AvsNoLicenceGuest: Keine Fahrberechtigung (Gast, Fahrberechtigungserwerb nicht möglich)
PaginationSize: Einträge pro Seite PaginationSize: Einträge pro Seite
PaginationPage: Angzeigte 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 #messages or constructors that are used all over the Code
Logo: Uni2work Logo: FRADrive
EmailInvitationWarning: This address could not be matched to any Uni2work user. An invitation will be sent via email. 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: — BoolIrrelevant: —
FieldPrimary: Major FieldPrimary: Major
FieldSecondary: Minor FieldSecondary: Minor
MultiEmailFieldTip: Multiple emails addresses may be specified (comma-separated) MultiEmailFieldTip: Multiple emails addresses may be specified (comma-separated)
MultiSelectTip: Multiple selection and desection via Ctrl-Click MultiSelectTip: Multiple selection and desection via Ctrl-Click
WeekDay: Day of the week WeekDay: Day of the week
LdapIdentificationOrEmail: Fraport AG-Kennung / email address Hours: Hours
SomeMonths: Months
SomeDays: Days
Months num: #{num} #{pluralEN num "Month" "Months"} Months num: #{num} #{pluralEN num "Month" "Months"}
Days num: #{num} #{pluralEN num "Day" "Days"} 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 ClusterVolatileQuickActionsEnabled: Quick actions enabled
AvsNoLicence: No driving licence AvsNoLicence: No driving licence
AvsLicenceVorfeld: Apron driving licence AvsLicenceVorfeld: Apron driving licence
AvsLicenceRollfeld: Maneuvering area driving licence AvsLicenceRollfeld: Maneuvering area driving licence
AvsNoLicenceGuest: No driving licence (Guest account, cannot acquire a diriving licence)
PaginationSize: Rows per Page PaginationSize: Rows per Page
PaginationPage: Page to show 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 # SPDX-License-Identifier: AGPL-3.0-or-later
@ -55,6 +55,8 @@ BtnUserAssimilate: Assimilieren
BtnCloseExam: Prüfung abschließen BtnCloseExam: Prüfung abschließen
BtnFinishExam: Prüfungsergebnisse sichtbar schalten BtnFinishExam: Prüfungsergebnisse sichtbar schalten
BtnConfirm: Bestätigen BtnConfirm: Bestätigen
BtnPerform: Ausführen
BtnCourseRegisterAdd: Personen suchen BtnCourseRegisterAdd: Personen suchen
BtnCourseRegisterConfirm: Ausgewählte Personen anmelden 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 # SPDX-License-Identifier: AGPL-3.0-or-later
@ -55,6 +55,8 @@ BtnUserAssimilate: Assimilate
BtnCloseExam: Close exam BtnCloseExam: Close exam
BtnFinishExam: Make results visible BtnFinishExam: Make results visible
BtnConfirm: Confirm BtnConfirm: Confirm
BtnPerform: Perform
BtnCourseRegisterAdd: Search persons BtnCourseRegisterAdd: Search persons
BtnCourseRegisterConfirm: Register selected persons BtnCourseRegisterConfirm: Register selected persons
BtnCourseRegisterAbort: Abort BtnCourseRegisterAbort: Abort
BtnCloseReload: Close and reload

View File

@ -20,3 +20,7 @@ ExceptionNoOccurAt: Termin
ExceptionKind: Termin ... ExceptionKind: Termin ...
ExceptionKindOccur: Findet statt ExceptionKindOccur: Findet statt
ExceptionKindNoOccur: Findet nicht 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 ... ExceptionKind: Event ...
ExceptionKindOccur: Does occur ExceptionKindOccur: Does occur
ExceptionKindNoOccur: Does not 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 BreadcrumbUpload !ident-ok: Upload
BreadcrumbUserAdd: Benutzer:in anlegen BreadcrumbUserAdd: Benutzer:in anlegen
BreadcrumbUserNotifications: Benachrichtigungs-Einstellungen BreadcrumbUserNotifications: Benachrichtigungs-Einstellungen
BreadcrumbUserRecipients: Benachrichtigungs-Empfänger
BreadcrumbUserPassword: Passwort BreadcrumbUserPassword: Passwort
BreadcrumbAdminHeading !ident-ok: Administration BreadcrumbAdminHeading !ident-ok: Administration
BreadcrumbAdminFeaturesHeading: Studiengänge BreadcrumbAdminFeaturesHeading: Studiengänge

View File

@ -6,7 +6,7 @@ BreadcrumbCsvOptions: csv-options
BreadcrumbSubmissionFile: File BreadcrumbSubmissionFile: File
BreadcrumbSubmissionUserInvite: Invitation to participate in a submission BreadcrumbSubmissionUserInvite: Invitation to participate in a submission
BreadcrumbCryptoIDDispatch: CryptoID-redirect BreadcrumbCryptoIDDispatch: CryptoID-redirect
BreadcrumbCourseNotes: Course type notes BreadcrumbCourseNotes: Course category notes
BreadcrumbHiWis: Correctors BreadcrumbHiWis: Correctors
BreadcrumbMaterial: Material BreadcrumbMaterial: Material
BreadcrumbSheet: Exercise sheet BreadcrumbSheet: Exercise sheet
@ -14,7 +14,7 @@ BreadcrumbTutorial: Course
BreadcrumbExam: Exam BreadcrumbExam: Exam
BreadcrumbCourseRegister: Register BreadcrumbCourseRegister: Register
BreadcrumbCourseFavourite: Favourite BreadcrumbCourseFavourite: Favourite
BreadcrumbCourse: Course type BreadcrumbCourse: Course category
BreadcrumbTerm: Year BreadcrumbTerm: Year
BreadcrumbSchool: Department BreadcrumbSchool: Department
BreadcrumbUser: User BreadcrumbUser: User
@ -28,11 +28,11 @@ BreadcrumbUserDelete: Delete user account
BreadcrumbUserHijack: Hijack user session BreadcrumbUserHijack: Hijack user session
BreadcrumbSystemMessage: System message BreadcrumbSystemMessage: System message
BreadcrumbSubmission: Submission BreadcrumbSubmission: Submission
BreadcrumbCourseNews: Course type news BreadcrumbCourseNews: Course category news
BreadcrumbCourseNewsDelete: Delete course type news BreadcrumbCourseNewsDelete: Delete course category news
BreadcrumbCourseEventDelete: Delete course type occurrence BreadcrumbCourseEventDelete: Delete course category occurrence
BreadcrumbProfile: Settings BreadcrumbProfile: Settings
BreadcrumbCourseParticipantInvitation: Invitation to be a course type participant BreadcrumbCourseParticipantInvitation: Invitation to be a course category participant
BreadcrumbMaterialArchive: Archive BreadcrumbMaterialArchive: Archive
BreadcrumbMaterialFile: File BreadcrumbMaterialFile: File
BreadcrumbMaterialVideo: Video BreadcrumbMaterialVideo: Video
@ -57,8 +57,8 @@ BreadcrumbExternalExamUsers: Participants
BreadcrumbExternalExamGrades: Exam results BreadcrumbExternalExamGrades: Exam results
BreadcrumbExternalExamStaffInvite: Invitation BreadcrumbExternalExamStaffInvite: Invitation
BreadcrumbExternalExamCorrect: Enter exam results BreadcrumbExternalExamCorrect: Enter exam results
BreadcrumbParticipantsList: Lists of course type participants BreadcrumbParticipantsList: Lists of course category participants
BreadcrumbParticipants: Course type participants BreadcrumbParticipants: Course category participants
BreadcrumbExamAutoOccurrence: Automatic occurrence/room distribution BreadcrumbExamAutoOccurrence: Automatic occurrence/room distribution
BreadcrumbStorageKey: Generate storage key BreadcrumbStorageKey: Generate storage key
BreadcrumbMessageHide: Hide BreadcrumbMessageHide: Hide
@ -71,6 +71,7 @@ BreadcrumbError: Error
BreadcrumbUpload: Upload BreadcrumbUpload: Upload
BreadcrumbUserAdd: Add user BreadcrumbUserAdd: Add user
BreadcrumbUserNotifications: Notification settings BreadcrumbUserNotifications: Notification settings
BreadcrumbUserRecipients: Notification recipients
BreadcrumbUserPassword: Password BreadcrumbUserPassword: Password
BreadcrumbAdminHeading: Administration BreadcrumbAdminHeading: Administration
BreadcrumbAdminFeaturesHeading: Features of study BreadcrumbAdminFeaturesHeading: Features of study
@ -96,7 +97,7 @@ BreadcrumbTermShow: Years
BreadcrumbTermCreate: Create new year BreadcrumbTermCreate: Create new year
BreadcrumbTermEdit: Edit year BreadcrumbTermEdit: Edit year
BreadcrumbTermCurrent: Current year BreadcrumbTermCurrent: Current year
BreadcrumbParticipantsIntersect: Common course type participants BreadcrumbParticipantsIntersect: Common course category participants
BreadcrumbCourseList: Courses BreadcrumbCourseList: Courses
BreadcrumbCourseNew: Create new course BreadcrumbCourseNew: Create new course
BreadcrumbCourseEdit: Edit course BreadcrumbCourseEdit: Edit course
@ -105,14 +106,14 @@ BreadcrumbCourseAddMembers: Add participants
BreadcrumbCourseExamOffice: Exam offices BreadcrumbCourseExamOffice: Exam offices
BreadcrumbCorrectionsAssign: Assign corrections BreadcrumbCorrectionsAssign: Assign corrections
BreadcrumbSheetList: Exercise sheets BreadcrumbSheetList: Exercise sheets
BreadcrumbCourseCommunication: Course type message (email) BreadcrumbCourseCommunication: Course category message (email)
BreadcrumbTutorialList: Courses BreadcrumbTutorialList: Courses
BreadcrumbTutorialNew: Create new course BreadcrumbTutorialNew: Create new course
BreadcrumbCourseDelete: Delete course BreadcrumbCourseDelete: Delete course
BreadcrumbCourseNewsNew: Add course type news BreadcrumbCourseNewsNew: Add course category news
BreadcrumbCourseNewsEdit: Edit course type news BreadcrumbCourseNewsEdit: Edit course category news
BreadcrumbCourseEventNew: New course type occurrence BreadcrumbCourseEventNew: New course category occurrence
BreadcrumbCourseEventEdit: Edit course type occurrence BreadcrumbCourseEventEdit: Edit course category occurrence
BreadcrumbExamList: Exams BreadcrumbExamList: Exams
BreadcrumbExamNew: Create new exam BreadcrumbExamNew: Create new exam
BreadcrumbExamEdit: Edit exam BreadcrumbExamEdit: Edit exam
@ -122,7 +123,7 @@ BreadcrumbExamAddMembers: Add exam participants
BreadcrumbExamCorrect: Grade exams BreadcrumbExamCorrect: Grade exams
BreadcrumbTutorialDelete: Delete course BreadcrumbTutorialDelete: Delete course
BreadcrumbTutorialEdit: Edit course BreadcrumbTutorialEdit: Edit course
BreadcrumbTutorialComm: Send course type message BreadcrumbTutorialComm: Send course category message
BreadcrumbSheetEdit: Edit exercise sheet BreadcrumbSheetEdit: Edit exercise sheet
BreadcrumbSheetDelete: Delete exercise sheet BreadcrumbSheetDelete: Delete exercise sheet
BreadcrumbSubmissions: Submissions 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 # SPDX-License-Identifier: AGPL-3.0-or-later
@ -33,6 +33,7 @@ MenuCourseIcon: Kurse
MenuCourseMembers: Kursartteilnehmer:innen MenuCourseMembers: Kursartteilnehmer:innen
MenuCourseAddMembers: Kursartteilnehmer:innen hinzufügen MenuCourseAddMembers: Kursartteilnehmer:innen hinzufügen
MenuTutorialAddMembers: Kursteilnehmer:innen hinzufügen MenuTutorialAddMembers: Kursteilnehmer:innen hinzufügen
MenuTutorialExam exn@ExamName: Kursprüfung #{exn} bearbeiten
MenuCourseCommunication: Kursartmitteilung (EMail) MenuCourseCommunication: Kursartmitteilung (EMail)
MenuCourseExamOffice: Prüfungsbeauftragte MenuCourseExamOffice: Prüfungsbeauftragte
MenuTermShow: Jahr MenuTermShow: Jahr
@ -87,6 +88,7 @@ MenuTutorialComm: Mitteilung an Teilnehmer:innen
MenuExamList: Prüfungen MenuExamList: Prüfungen
MenuExamNew: Neue Prüfung anlegen MenuExamNew: Neue Prüfung anlegen
MenuExamEdit: Prüfung bearbeiten MenuExamEdit: Prüfung bearbeiten
MenuExamEditComplete: Prüfung vollständig überarbeiten
MenuExamUsers: Teilnehmer:innen MenuExamUsers: Teilnehmer:innen
MenuExamGrades: Prüfungsleistungen MenuExamGrades: Prüfungsleistungen
MenuExamAddMembers: Prüfungsteilnehmer hinzufügen MenuExamAddMembers: Prüfungsteilnehmer hinzufügen
@ -97,6 +99,8 @@ MenuExamOfficeUsers: Benutzer:innen
MenuLecturerInvite: Funktionäre hinzufügen MenuLecturerInvite: Funktionäre hinzufügen
MenuSchoolList: Bereiche MenuSchoolList: Bereiche
MenuSchoolNew: Neuen Bereich anlegen MenuSchoolNew: Neuen Bereich anlegen
MenuSchoolDay ssh@SchoolId d@Text: #{d} #{unSchoolKey ssh} Tagesansicht
MenuSchoolDayCheck: Konsistenzprüfung
MenuExternalExamGrades: Prüfungsleistungen MenuExternalExamGrades: Prüfungsleistungen
MenuExternalExamUsers: Teilnehmer:innen MenuExternalExamUsers: Teilnehmer:innen
MenuExternalExamEdit: Bearbeiten MenuExternalExamEdit: Bearbeiten
@ -119,8 +123,9 @@ MenuCourseEventEdit: Kursarttermin bearbeiten
MenuLanguage: Sprache MenuLanguage: Sprache
MenuQualifications: Qualifikationen MenuQualifications: Qualifikationen
MenuQualificationEdit: Bearbeiten
MenuQualificationNew: Neue Qualifikation erstellen
MenuLms !ident-ok: ELearning MenuLms !ident-ok: ELearning
MenuLmsEdit: Bearbeiten ELearning
MenuLmsUser: Benutzerqualifikationen MenuLmsUser: Benutzerqualifikationen
MenuLmsUserSchool: Bereichs Benutzerqualifikationen MenuLmsUserSchool: Bereichs Benutzerqualifikationen
MenuLmsUserAll: Alle Benutzerqualifikationen MenuLmsUserAll: Alle Benutzerqualifikationen
@ -136,6 +141,7 @@ MenuFirms: Firmen
MenuFirmUsers: Angehörige MenuFirmUsers: Angehörige
MenuFirmSupervisors: Ansprechpartner MenuFirmSupervisors: Ansprechpartner
MenuFirmsComm: Mitteilung MenuFirmsComm: Mitteilung
MenuFirmsSupervision: Probleme Ansprechpartnerbeziehungen
MenuInterfaces: Schnittstellen MenuInterfaces: Schnittstellen
MenuSap: SAP Schnittstelle MenuSap: SAP Schnittstelle
@ -143,12 +149,18 @@ MenuSap: SAP Schnittstelle
MenuAvs: AVS Schnittstelle MenuAvs: AVS Schnittstelle
MenuAvsSynchError: AVS Problemübersicht MenuAvsSynchError: AVS Problemübersicht
MenuLdap: LDAP Schnittstelle MenuLdap: LDAP Schnittstelle
MenuApc: Druckerei MenuApc: Druck
MenuPrintSend: Manueller Briefversand MenuPrintSend: Manueller Briefversand
MenuPrintDownload: Brief herunterladen MenuPrintDownload: Brief herunterladen
MenuPrintLog: LPR Schnittstelle MenuPrintLog: LPR Schnittstelle
MenuPrintAck: Druckbestätigung MenuPrintAck: Druckbestätigung
MenuCommCenter: Benachrichtigungen
MenuMailCenter: EMails
MenuMailHtml !ident-ok: Html
MenuMailPlain !ident-ok: Text
MenuMailAttachment: Anhang
MenuApiDocs: API-Dokumentation (Englisch) MenuApiDocs: API-Dokumentation (Englisch)
MenuSwagger !ident-ok: OpenAPI 2.0 (Swagger) 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 # SPDX-License-Identifier: AGPL-3.0-or-later
@ -6,7 +6,7 @@ MenuAdminHeading: Administration
MenuAdminFeaturesHeading: Features of study MenuAdminFeaturesHeading: Features of study
MenuInfoLecturerTitle: Information for course administrators MenuInfoLecturerTitle: Information for course administrators
MenuInfoLecturerCourses: Courses MenuInfoLecturerCourses: Courses
MenuInfoLecturerExercises: Course type Exercises MenuInfoLecturerExercises: Course category Exercises
MenuInfoLecturerTutorials: Courses MenuInfoLecturerTutorials: Courses
MenuInfoLecturerExams: Exams MenuInfoLecturerExams: Exams
MenuCsvOptions: CSV-options MenuCsvOptions: CSV-options
@ -28,12 +28,13 @@ MenuHelp: Support
MenuProfile: Settings MenuProfile: Settings
MenuLogin: Login MenuLogin: Login
MenuLogout: Logout MenuLogout: Logout
MenuCourseList: Course types MenuCourseList: Course categorys
MenuCourseIcon: Courses MenuCourseIcon: Courses
MenuCourseMembers: Participants MenuCourseMembers: Participants
MenuCourseAddMembers: Add course type participants MenuCourseAddMembers: Add course category participants
MenuTutorialAddMembers: Add course 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 MenuCourseExamOffice: Exam offices
MenuTermShow: Semesters MenuTermShow: Semesters
MenuSubmissionDelete: Delete submission MenuSubmissionDelete: Delete submission
@ -48,7 +49,7 @@ MenuAdminErrMsg: Decrypt error message
MenuAdminTokens: Issue tokens MenuAdminTokens: Issue tokens
MenuProfileData: Personal information MenuProfileData: Personal information
MenuTermCreate: Create new year MenuTermCreate: Create new year
MenuCourseNew: Create new course type MenuCourseNew: Create new course category
MenuTermEdit: Edit year MenuTermEdit: Edit year
MenuTermCurrent: Current year MenuTermCurrent: Current year
MenuCorrection: Correction MenuCorrection: Correction
@ -83,10 +84,11 @@ MenuCorrectionsAssignSheet name: Assign corrections for #{name}
MenuAuthPreds: Authorisation settings MenuAuthPreds: Authorisation settings
MenuTutorialDelete: Delete course MenuTutorialDelete: Delete course
MenuTutorialEdit: Edit course MenuTutorialEdit: Edit course
MenuTutorialComm: Send course type message MenuTutorialComm: Send course category message
MenuExamList: Exams MenuExamList: Exams
MenuExamNew: Create new exam MenuExamNew: Create new exam
MenuExamEdit: Edit exam MenuExamEdit: Edit exam
MenuExamEditComplete: Revise entire exam
MenuExamUsers: Participants MenuExamUsers: Participants
MenuExamGrades: Exam results MenuExamGrades: Exam results
MenuExamAddMembers: Add exam participants MenuExamAddMembers: Add exam participants
@ -97,14 +99,16 @@ MenuExamOfficeUsers: Users
MenuLecturerInvite: Add functionaries MenuLecturerInvite: Add functionaries
MenuSchoolList: Departments MenuSchoolList: Departments
MenuSchoolNew: Create new department MenuSchoolNew: Create new department
MenuSchoolDay ssh d: #{d} #{unSchoolKey ssh} Agenda
MenuSchoolDayCheck: Consistence check
MenuExternalExamGrades: Exam results MenuExternalExamGrades: Exam results
MenuExternalExamUsers: Participants MenuExternalExamUsers: Participants
MenuExternalExamEdit: Edit MenuExternalExamEdit: Edit
MenuExternalExamNew: New external exam MenuExternalExamNew: New external exam
MenuExternalExamList: External exams MenuExternalExamList: External exams
MenuExternalExamCorrect: Enter exam results MenuExternalExamCorrect: Enter exam results
MenuParticipantsList: Lists of course type participants MenuParticipantsList: Lists of course category participants
MenuParticipantsIntersect: Common course type participants MenuParticipantsIntersect: Common course category participants
MenuFaq: FAQ MenuFaq: FAQ
MenuSheetPersonalisedFiles: Download personalised sheet files MenuSheetPersonalisedFiles: Download personalised sheet files
MenuCourseSheetPersonalisedFiles: Download template for personalised sheet files MenuCourseSheetPersonalisedFiles: Download template for personalised sheet files
@ -112,17 +116,18 @@ MenuAdminCrontab: Crontab
MenuAdminJobs: Job queue MenuAdminJobs: Job queue
MenuGlossary: Glossary MenuGlossary: Glossary
MenuVersion: Version history MenuVersion: Version history
MenuCourseNewsNew: Add course type news MenuCourseNewsNew: Add course category news
MenuCourseNewsEdit: Edit course type news MenuCourseNewsEdit: Edit course category news
MenuCourseEventNew: New course type occurrence MenuCourseEventNew: New course category occurrence
MenuCourseEventEdit: Edit course type occurrence MenuCourseEventEdit: Edit course category occurrence
MenuLanguage: Language MenuLanguage: Language
MenuQualifications: Qualifications MenuQualifications: Qualifications
MenuQualificationEdit: Edit
MenuQualificationNew: Create new qualification
MenuLms: Elearning MenuLms: Elearning
MenuLmsEdit: Edit elearning
MenuLmsUser: User Qualifications MenuLmsUser: User Qualifications
MenuLmsUserSchool: Institute User Qualifications MenuLmsUserSchool: Department User Qualifications
MenuLmsUserAll: All User Qualifications MenuLmsUserAll: All User Qualifications
MenuLmsUsers: Legacy download elearning users MenuLmsUsers: Legacy download elearning users
MenuLmsUpload: Upload MenuLmsUpload: Upload
@ -136,6 +141,7 @@ MenuFirms: Companies
MenuFirmUsers: Associates MenuFirmUsers: Associates
MenuFirmSupervisors: Supervisors MenuFirmSupervisors: Supervisors
MenuFirmsComm: Messaging MenuFirmsComm: Messaging
MenuFirmsSupervision: Problems supervisionship
MenuInterfaces: Interfaces MenuInterfaces: Interfaces
MenuSap: SAP Interface MenuSap: SAP Interface
@ -143,12 +149,18 @@ MenuSap: SAP Interface
MenuAvs: AVS Interface MenuAvs: AVS Interface
MenuAvsSynchError: AVS Problem Overview MenuAvsSynchError: AVS Problem Overview
MenuLdap: LDAP Interface MenuLdap: LDAP Interface
MenuApc: Printing MenuApc: Print
MenuPrintSend: Send Letter MenuPrintSend: Send Letter
MenuPrintDownload: Download Letter MenuPrintDownload: Download Letter
MenuPrintLog: LPR Interface MenuPrintLog: LPR Interface
MenuPrintAck: Acknowledge Printing MenuPrintAck: Acknowledge Printing
MenuCommCenter: Notifications
MenuMailCenter: Email
MenuMailHtml: Html
MenuMailPlain: Text
MenuMailAttachment: Attachment
MenuApiDocs: API documentation MenuApiDocs: API documentation
MenuSwagger: OpenAPI 2.0 (Swagger) MenuSwagger: OpenAPI 2.0 (Swagger)

View File

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

View File

@ -12,8 +12,8 @@ NewsHeading: News
InfoHeading: Information InfoHeading: Information
LegalHeading: Legal LegalHeading: Legal
VersionHeading: Version history VersionHeading: Version history
SystemMessageHeading: Uni2work system message SystemMessageHeading: FRADrive system message
SystemMessageListHeading: Uni2work system message SystemMessageListHeading: FRADrive system messages
HeadingHelpRequest: Support request/Suggestion HeadingHelpRequest: Support request/Suggestion
ProfileHeading: Settings ProfileHeading: Settings
ProfileDataHeading: Personal information ProfileDataHeading: Personal information
@ -29,8 +29,8 @@ HeadingTermEditTid tid: Edit year #{tid}
TermCourseListHeading tid: Courses #{tid} TermCourseListHeading tid: Courses #{tid}
TermSchoolCourseListHeading tid school: Courses #{tid}, #{school} TermSchoolCourseListHeading tid school: Courses #{tid}, #{school}
CourseListTitle: All courses CourseListTitle: All courses
CourseNewHeading: Create new course type CourseNewHeading: Create new course category
CourseEditHeading tid ssh csh: Edit course type #{tid}-#{ssh}-#{csh} CourseEditHeading tid ssh csh: Edit course category #{tid}-#{ssh}-#{csh}
SubmissionsCourse tid ssh csh: All submissions for Course #{tid}-#{ssh}-#{csh} SubmissionsCourse tid ssh csh: All submissions for Course #{tid}-#{ssh}-#{csh}
SubmissionsSheet sheetName: Submissions for #{sheetName} SubmissionsSheet sheetName: Submissions for #{sheetName}
SheetList tid ssh csh : #{tid}-#{ssh}-#{csh} Sheet Overview 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} 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 SheetTitleNew tid@TermId ssh@SchoolId csh@CourseShorthand : #{tid}-#{ssh}-#{csh}: New sheet
SheetEditHead tid ssh csh sheetName: #{tid}-#{ssh}-#{csh} Edit #{sheetName} 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 SubmissionEditHead tid ssh csh sheetName: #{tid}-#{ssh}-#{csh} #{sheetName}: Edit/Create submission
CorrectionHead tid ssh csh sheetName cid: #{tid}-#{ssh}-#{csh} #{sheetName}: Marking CorrectionHead tid ssh csh sheetName cid: #{tid}-#{ssh}-#{csh} #{sheetName}: Marking
CorrectionsTitle: Assigned corrections CorrectionsTitle: Assigned corrections
@ -48,8 +48,8 @@ CorrGrade: Mark submissions
TableHeadingCsvImport: CSV import TableHeadingCsvImport: CSV import
TableHeadingCsvExport: CSV export TableHeadingCsvExport: CSV export
FavouritesEmptyTip: Your courses and recently visited courses are shown here. 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. 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 type are currently not available. FavouritesUnavailableTip: Quick Actions for this course category are currently not available.
NavigationFavourites: Favourites NavigationFavourites: Favourites
ErrorResponseTitleInternalError internalError: An internal error occurred ErrorResponseTitleInternalError internalError: An internal error occurred
ErrorResponseTitleInvalidArgs invalidArgs: Request contained invalid arguments 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 # SPDX-License-Identifier: AGPL-3.0-or-later
@ -47,12 +47,12 @@ TablePassed: Bestanden
TableNotPassed: Nicht bestanden TableNotPassed: Nicht bestanden
TableTutorialTutors: Ausbilder TableTutorialTutors: Ausbilder
TableTutorialName: Bezeichnung TableTutorialName: Bezeichnung
TableTutorialType: Art TableTutorialType: Typ
TableTutorialRoom: Regulärer Raum TableTutorialRoom: Raum
TableTutorialRoomHidden: Raum nur für Teilnehmer TableTutorialRoomHidden: Raum nur für Teilnehmer
TableTutorialRoomIsUnset !ident-ok: — TableTutorialRoomIsUnset !ident-ok: —
TableTutorialRoomIsHidden: Raum wird nur Teilnehmern angezeigt TableTutorialRoomIsHidden: Raum wird nur Teilnehmern angezeigt
TableTutorialTime: Zeit TableTutorialOccurrence: Termin
TableTutorialDeregisterUntil: Abmeldungen bis TableTutorialDeregisterUntil: Abmeldungen bis
TableTutorialFirstDay: Starttag TableTutorialFirstDay: Starttag
TableActionsHead: Aktionen TableActionsHead: Aktionen
@ -73,15 +73,22 @@ TableDiffDaysTooltip: Zeitspanne nach ISO 8601. Beispiel: "P2Y3M4D" ist eine Zei
TableExamOfficeLabel: Label-Name TableExamOfficeLabel: Label-Name
TableExamOfficeLabelStatus: Label-Farbe TableExamOfficeLabelStatus: Label-Farbe
TableExamOfficeLabelPriority: Label-Priorität TableExamOfficeLabelPriority: Label-Priorität
TableQualification: Qualifikation
TableQualifications: Qualifikationen TableQualifications: Qualifikationen
TableCompany: Firma TableCompany: Firma
TableCompanyFilter: Firma oder Nummer TableCompanyFilter: Firma oder Nummer
TableCompanyShort: Firmenkürzel TableCompanyShort: Firmenkürzel
TableCompanies: Firmen TableCompanies: Firmen
TablePrimeCompany: Primäre Firma
TablePrimeCompanyShort: Kürzel primäre Firma
TableBookingCompany: Buchende Firma
TableBookingCompanyShort: Kürzel buchende Firma
TableCompanyNo: Firmennummer TableCompanyNo: Firmennummer
TableCompanyNos: Firmennummern TableCompanyNos: Firmennummern
TableCompanyUser: Firmenangehöriger TableCompanyUser: Firmenangehöriger
TableCompanyNrUsers: Firmenangehörige TableCompanyNrUsers: Firmenangehörige
TableCompanyNrSecondaryUsers: Sekundäre Firmenangehörige
TableCompanyReason: Notiz
TableCompanyNrSupers: Ansprechpartner TableCompanyNrSupers: Ansprechpartner
TableCompanyNrEmpSupervised: Firmenangehörige mit Ansprechpartner TableCompanyNrEmpSupervised: Firmenangehörige mit Ansprechpartner
TableCompanyNrEmpRerouted: Firmenangehörige mit Umleitung TableCompanyNrEmpRerouted: Firmenangehörige mit Umleitung
@ -91,8 +98,13 @@ TableCompanyNrSupersDefault: Standard Ansprechpartner
TableCompanyNrForeignSupers: Firmenfremde Ansprechpartner TableCompanyNrForeignSupers: Firmenfremde Ansprechpartner
TableCompanyNrRerouteDefault: Standard Umleitungen TableCompanyNrRerouteDefault: Standard Umleitungen
TableCompanyNrRerouteActive: Aktive Umleitungen TableCompanyNrRerouteActive: Aktive Umleitungen
TableRerouteActive: Umleitung
TableCompanyPostalPreference: Benachrichtigungspräferenz neue Firmenangehörige TableCompanyPostalPreference: Benachrichtigungspräferenz neue Firmenangehörige
TableCompanyPinPassword: Pin Passwort für PDF Anhänge
TableSupervisor: Ansprechpartner TableSupervisor: Ansprechpartner
TableSupervisorActive: Aktiver Ansprechpartner
TableSupervisee: Klient
TableReason: Begründung
TableCreationTime: Erstellungszeit TableCreationTime: Erstellungszeit
TableJob !ident-ok: Job TableJob !ident-ok: Job
TableJobContent !ident-ok: Parameter TableJobContent !ident-ok: Parameter
@ -100,10 +112,13 @@ TableJobLockTime: Bearbeitung seit
TableJobLockInstance: Bearbeiter TableJobLockInstance: Bearbeiter
TableJobCreationInstance: Ersteller TableJobCreationInstance: Ersteller
ActJobDelete: Job entfernen ActJobDelete: Job entfernen
ActJobDeleteForce n@Int: Auch vor #{pluralDEnN n "Minute"} gesperrte Jobs entfernen
TableJobActDeleteFeedback n@Int m@Int: #{n}/#{m} Jobs entfernt 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. 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. 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. 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 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 # SPDX-License-Identifier: AGPL-3.0-or-later
@ -20,7 +20,7 @@ TableMatrikelNr: AVS person no
TableSex: Sex TableSex: Sex
TableBirthday: Birthday TableBirthday: Birthday
TableSchool: Department TableSchool: Department
TableCourse: Course TableCourse: Course category
TableCourseMembers: Participants TableCourseMembers: Participants
TableExamOccurrence: Occurrence/room TableExamOccurrence: Occurrence/room
TableExamName: Name TableExamName: Name
@ -48,14 +48,14 @@ TableNotPassed: Failed
TableTutorialTutors: Instructors TableTutorialTutors: Instructors
TableTutorialName: Name TableTutorialName: Name
TableTutorialType: Type TableTutorialType: Type
TableTutorialRoom: Regular room TableTutorialRoom: Room
TableTutorialRoomHidden: Room only for participants TableTutorialRoomHidden: Room only for participants
TableTutorialRoomIsUnset: — TableTutorialRoomIsUnset: —
TableTutorialRoomIsHidden: Room is only displayed to participants TableTutorialRoomIsHidden: Room is only displayed to participants
TableTutorialDeregisterUntil: Deregister until TableTutorialDeregisterUntil: Deregister until
TableTutorialFirstDay: Start date TableTutorialFirstDay: Start date
TableActionsHead: Actions TableActionsHead: Actions
TableTutorialTime: Time TableTutorialOccurrence: Session
TableNoFilter: No restriction TableNoFilter: No restriction
TableUserMatriculation: AVS number TableUserMatriculation: AVS number
TableColumnStudyFeatures: Features of study TableColumnStudyFeatures: Features of study
@ -73,15 +73,22 @@ TableDiffDaysTooltip: Duration given according to ISO 8601. Example: "P2Y3M4D" i
TableExamOfficeLabel: Label name TableExamOfficeLabel: Label name
TableExamOfficeLabelStatus: Label colour TableExamOfficeLabelStatus: Label colour
TableExamOfficeLabelPriority: Label priority TableExamOfficeLabelPriority: Label priority
TableQualification: Qualification
TableQualifications: Qualifications TableQualifications: Qualifications
TableCompany: Company TableCompany: Company
TableCompanyFilter: Company/Nr TableCompanyFilter: Company/Nr
TableCompanyShort: Company shorthand TableCompanyShort: Company shorthand
TableCompanies: Companies TableCompanies: Companies
TablePrimeCompany: Primary company
TablePrimeCompanyShort: Primary company shorthand
TableBookingCompany: Booking company
TableBookingCompanyShort: Booking company shorthand
TableCompanyNo: Company number TableCompanyNo: Company number
TableCompanyNos: Company numbers TableCompanyNos: Company numbers
TableCompanyUser: Associate TableCompanyUser: Associate
TableCompanyNrUsers: Associates TableCompanyNrUsers: Associates
TableCompanyNrSecondaryUsers: Secondary Associates
TableCompanyReason: Note
TableCompanyNrSupers: Supervisors TableCompanyNrSupers: Supervisors
TableCompanyNrEmpSupervised: Supervised employees TableCompanyNrEmpSupervised: Supervised employees
TableCompanyNrEmpRerouted: Employees having reroute TableCompanyNrEmpRerouted: Employees having reroute
@ -91,8 +98,13 @@ TableCompanyNrSupersDefault: Default supervisors
TableCompanyNrForeignSupers: External Supervisors TableCompanyNrForeignSupers: External Supervisors
TableCompanyNrRerouteDefault: Default reroutes TableCompanyNrRerouteDefault: Default reroutes
TableCompanyNrRerouteActive: Active reroutes TableCompanyNrRerouteActive: Active reroutes
TableRerouteActive: Reroute
TableCompanyPostalPreference: Default notification preference TableCompanyPostalPreference: Default notification preference
TableCompanyPinPassword: Pin password for PDF attachments
TableSupervisor: Supervisor TableSupervisor: Supervisor
TableSupervisorActive: Active supervisor
TableSupervisee: Supervisee
TableReason: Reason
TableCreationTime: Creation TableCreationTime: Creation
TableJob !ident-ok: Job TableJob !ident-ok: Job
TableJobContent !ident-ok: Parameters TableJobContent !ident-ok: Parameters
@ -100,10 +112,13 @@ TableJobLockTime: Lock time
TableJobLockInstance: Worker TableJobLockInstance: Worker
TableJobCreationInstance: Creator TableJobCreationInstance: Creator
ActJobDelete: Delete job ActJobDelete: Delete job
ActJobDeleteForce n: Also delete jobs locked #{pluralENsN n "minute"} ago
TableJobActDeleteFeedback n@Int m@Int: #{n}/#{m} queued jobs deleted 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. 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. 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. 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 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 # 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}“ RGExamRegistered examn@ExamName: Angemeldet zur Prüfung „#{examn}“
RGSheetSubmittor shn@SheetName: Abgebende für das Übungsblatt „#{shn}“ RGSheetSubmittor shn@SheetName: Abgebende für das Übungsblatt „#{shn}“
CommSubject: Betreff CommSubject: Betreff
CommContent: Inhalt
CommAttachments: Anhänge 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. 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 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. 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. MultiUserFieldInvitationExplanationAlways: Es wird an alle Adressen, die Sie hier angeben, eine Einladung per E-Mail versandt.
AmbiguousEmail: E-Mail-Adresse nicht eindeutig AmbiguousEmail: E-Mail-Adresse nicht eindeutig
UnknownEmail: E-Mail-Adresse konnte keinem bekannten Benutzer zugeordnet werden
InvalidEmailAddress: E-Mail-Adresse ist ungültig InvalidEmailAddress: E-Mail-Adresse ist ungültig
InvalidEmailAddressWith e@Text: E-Mail-Adresse #{show e} ist ungültig InvalidEmailAddressWith e@Text: E-Mail-Adresse #{show e} ist ungültig
MailFileAttachment: Dateianhang
UtilExamResultGrade: Note UtilExamResultGrade: Note
UtilExamResultPass: Bestanden/Nicht Bestanden UtilExamResultPass: Bestanden/Nicht Bestanden
UtilExamResultNoShow: Nicht erschienen UtilExamResultNoShow: Nicht erschienen
@ -89,6 +92,7 @@ UtilExamResultVoided: Entwertet
CourseOption tid@TermId ssh@SchoolId csh@CourseShorthand coursen@CourseName !ident-ok: #{tid} - #{ssh} - #{csh}: #{coursen} CourseOption tid@TermId ssh@SchoolId csh@CourseShorthand coursen@CourseName !ident-ok: #{tid} - #{ssh} - #{csh}: #{coursen}
RoomReferenceNone !ident-ok: — RoomReferenceNone !ident-ok: —
RoomReferenceSimple !ident-ok: Text RoomReferenceSimple !ident-ok: Text
RoomReferenceSimpleAt r@Text: in Raum #{r}
RoomReferenceLink: Link & Anweisungen RoomReferenceLink: Link & Anweisungen
RoomReferenceSimpleText: Raum RoomReferenceSimpleText: Raum
RoomReferenceSimpleTextPlaceholder: Raum RoomReferenceSimpleTextPlaceholder: Raum
@ -96,9 +100,11 @@ RoomReferenceLinkLink !ident-ok: Link
RoomReferenceLinkLinkPlaceholder !ident-ok: URL RoomReferenceLinkLinkPlaceholder !ident-ok: URL
RoomReferenceLinkInstructions: Anweisungen RoomReferenceLinkInstructions: Anweisungen
RoomReferenceLinkInstructionsPlaceholder: Anweisungen RoomReferenceLinkInstructionsPlaceholder: Anweisungen
UtilNoneSet: Keine angegeben
UtilEmptyChoice: Auswahl war leer UtilEmptyChoice: Auswahl war leer
UtilEmptyNoChangeTip: Eine leere Eingabe belässt den vorherigen Wert unverändert. UtilEmptyNoChangeTip: Eine leere Eingabe belässt den vorherigen Wert unverändert.
MultiNoSelection: Keine Auswahl MultiNoSelection: Keine Auswahl
MustBePositive: muss positiv sein
#invitation.hs #invitation.hs
InvitationAction: Aktion 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 # SPDX-License-Identifier: AGPL-3.0-or-later
#communication.hs #communication.hs
RecipientCustom: Custom recipients RecipientCustom: Custom recipients
RGCourseParticipants: Course type participants RGCourseParticipants: Course category participants
RGCourseLecturers: Course administrators RGCourseLecturers: Course administrators
RGCourseCorrectors: Course type correctors RGCourseCorrectors: Course category correctors
RGCourseTutors: Course instructors 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 RGCourseUnacceptedApplicants: Applicants not accepted
RecipientToggleAll: All/None RecipientToggleAll: All/None
CommCourseTestSubject customSubject: [TEST] #{customSubject} CommCourseTestSubject customSubject: [TEST] #{customSubject}
UtilCommCourseSubject: Course type message UtilCommCourseSubject: Course category message
UtilCommFirmSubject: Company message UtilCommFirmSubject: Company message
CommRecipients: Recipients CommRecipients: Recipients
CommRecipientsTip: You always receive a copy of the message CommRecipientsTip: You always receive a copy of the message
@ -25,8 +25,9 @@ RGTutorialParticipants tutn: Course participants (#{tutn})
RGExamRegistered examn: Registered for exam “#{examn}” RGExamRegistered examn: Registered for exam “#{examn}”
RGSheetSubmittor shn: Submitted for exercise sheet “#{shn}” RGSheetSubmittor shn: Submitted for exercise sheet “#{shn}”
CommSubject: Subject CommSubject: Subject
CommContent: Content
CommAttachments: Attachments 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"} CommSuccess n: Message was sent to #{n} #{pluralEN n "recipient" "recipients"}
CommTestSuccess: Message was sent only to yourself for testing purposes 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. 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. MultiUserFieldInvitationExplanationAlways: An invitation will be sent via email to all addresses you enter here.
AmbiguousEmail: Email address is ambiguous AmbiguousEmail: Email address is ambiguous
UnknownEmail: Email adresse is not associated with any registred user
InvalidEmailAddress: Email address is invalid InvalidEmailAddress: Email address is invalid
InvalidEmailAddressWith e: Email asdress #{show e} is invalid InvalidEmailAddressWith e: Email asdress #{show e} is invalid
MailFileAttachment: Attached file
UtilExamResultGrade: Grade UtilExamResultGrade: Grade
UtilExamResultPass: Passed/Failed UtilExamResultPass: Passed/Failed
UtilExamResultNoShow: Not present UtilExamResultNoShow: Not present
@ -89,6 +92,7 @@ UtilExamResultVoided: Voided
CourseOption tid ssh csh coursen: #{tid} - #{ssh} - #{csh}: #{coursen} CourseOption tid ssh csh coursen: #{tid} - #{ssh} - #{csh}: #{coursen}
RoomReferenceNone: — RoomReferenceNone: —
RoomReferenceSimple: Text RoomReferenceSimple: Text
RoomReferenceSimpleAt r: at room #{r}
RoomReferenceLink: Link & Instructions RoomReferenceLink: Link & Instructions
RoomReferenceSimpleText: Room RoomReferenceSimpleText: Room
RoomReferenceSimpleTextPlaceholder: Room RoomReferenceSimpleTextPlaceholder: Room
@ -96,9 +100,11 @@ RoomReferenceLinkLink: Link
RoomReferenceLinkLinkPlaceholder: URL RoomReferenceLinkLinkPlaceholder: URL
RoomReferenceLinkInstructions: Instructions RoomReferenceLinkInstructions: Instructions
RoomReferenceLinkInstructionsPlaceholder: Instructions RoomReferenceLinkInstructionsPlaceholder: Instructions
UtilNoneSet: None set
UtilEmptyChoice: Empty selection UtilEmptyChoice: Empty selection
UtilEmptyNoChangeTip: Existing values remain unchanged if this field is left empty. UtilEmptyNoChangeTip: Existing values remain unchanged if this field is left empty.
MultiNoSelection: No selection MultiNoSelection: No selection
MustBePositive: must be positive
#invitation.hs #invitation.hs
InvitationAction: Action 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 -- SPDX-License-Identifier: AGPL-3.0-or-later
@ -8,7 +8,7 @@ TransactionLog
instance InstanceId instance InstanceId
initiator UserId Maybe -- User associated with performing this action initiator UserId Maybe -- User associated with performing this action
remote IP Maybe -- Remote party that triggered this action via HTTP 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 deriving Eq Read Show Generic
InterfaceLog InterfaceLog
@ -26,6 +26,13 @@ InterfaceHealth
interface Text interface Text
subtype Text Maybe subtype Text Maybe
write Bool 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 UniqueInterfaceHealth interface subtype write !force -- Note that nullable fields must be either empty or unique
deriving Eq Read Show Generic 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 -- SPDX-License-Identifier: AGPL-3.0-or-later
@ -16,27 +16,19 @@
UserAvs UserAvs
personId AvsPersonId -- unique identifier for user throughout avs; newtype for Int personId AvsPersonId -- unique identifier for user throughout avs; newtype for Int
user UserId 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() lastSynch UTCTime default=now()
lastSynchError Text Maybe 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 UniqueUserAvsUser user
UniqueUserAvsId personId UniqueUserAvsId personId
deriving Generic Show 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 AvsSync
user UserId -- Note: we need to lookup UserAvs Entity anyway, so no benefit from storing AvsPersonId here user UserId -- Note: we need to lookup UserAvs Entity anyway, so no benefit from storing AvsPersonId here
creationTime UTCTime creationTime UTCTime
pause Day Maybe pause Day Maybe -- Don't synch if last synch after this day, otherwise synch
UniqueAvsSyncUser user 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 -- SPDX-License-Identifier: AGPL-3.0-or-later
-- Description of companies associated with users -- Description of companies associated with users
Company Company
name CompanyName -- == (CI Text) 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 FUTURE TODO: a shorthand will become available through the AVS interface in the future 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 avsId Int default=0 -- primary key from avs, use negative numbers for non-AVS companies
prefersPostal Bool default=false -- new company users prefers letters by post instead of email prefersPostal Bool default=true -- new company users prefers letters by post instead of email
postAddress StoredMarkup Maybe -- default company postal address postAddress StoredMarkup Maybe -- default company postal address, including company name
email UserEmail Maybe -- Case-insensitive generic company eMail address email UserEmail Maybe -- Case-insensitive generic company eMail address
UniqueCompanyName name pinPassword Bool default=true -- new company users only: should sensitive PDF email attachement be protected by a password?
UniqueCompanyShorthand shorthand -- UniqueCompanyName name -- Should be Unique in AVS, but we do not yet need to enforce it
-- UniqueCompanyAvsId avsId -- should be the case, unclear if enforcing works here, since we cannot query avs by company id -- UniqueCompanyShorthand shorthand -- unnecessary, since it is the primary key already
Primary shorthand -- newtype Key Company = CompanyKey { unCompanyKey :: CompanyShorthand } 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 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 TermSchoolCourseName term school name -- name must be unique within school and semester
deriving Generic deriving Generic
CourseEvent CourseEvent
type (CI Text) type (CI Text)
course CourseId OnDeleteCascade OnUpdateCascade course CourseId OnDeleteCascade OnUpdateCascade
room RoomReference Maybe roomHidden Bool default=false
roomHidden Bool default=false time (JSONB Occurrences)
time Occurrences note StoredMarkup Maybe
note StoredMarkup Maybe lastChanged UTCTime default=now()
lastChanged UTCTime default=now()
deriving Generic deriving Generic
CourseAppInstructionFile CourseAppInstructionFile

View File

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

View File

@ -20,11 +20,11 @@ CronLastExec
time UTCTime -- When was the job executed time UTCTime -- When was the job executed
instance InstanceId -- Which uni2work-instance did the work instance InstanceId -- Which uni2work-instance did the work
UniqueCronLastExec job UniqueCronLastExec job
deriving Generic deriving Generic Show
TokenBucket TokenBucket
ident TokenBucketIdent ident TokenBucketIdent
lastValue Int64 lastValue Int64
lastAccess UTCTime lastAccess UTCTime
Primary ident 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 -- SPDX-License-Identifier: AGPL-3.0-or-later
Qualification Qualification
-- INVARIANT: 2*refreshWithin < validDuration -- INVARIANT: 2*refreshWithin < validDuration
school SchoolId --TODO: Ansprechpartner der Schule in Briefe erwähnen school SchoolId -- 1
shorthand (CI Text) shorthand (CI Text) -- 2
name (CI Text) name (CI Text) -- 3
description StoredMarkup Maybe -- user-defined large Html, ought to contain full description description StoredMarkup Maybe -- 4 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 validDuration Int Maybe -- 5 if > 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) 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 -- notify users about renewal within this number of month/days before expiry; to be used with addGregorianDurationClip refreshWithin CalendarDiffDays Maybe -- 7 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 refreshReminder CalendarDiffDays Maybe -- 8 send a second notification about renewal within this number of month/days before expiry
elearningStart Bool -- automatically schedule e-refresher elearningStart Bool -- 9 automatically schedule e-refresher
-- elearningOnly Bool -- successful E-learing automatically increases validity. NO! elearningRenews Bool default=true -- 10 successful e-learing automatically increases validity automatically by validDuration
expiryNotification Bool default=true -- should expiryNotification be generated for this qualification? elearningLimit Int Maybe -- 11 limit of e-learning attempts, currently only for informative purposes, as it is enforced by LMS only
avsLicence AvsLicence Maybe -- if set, valid QualificationUsers are synchronized to AVS as a driving licence 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.
sapId Text Maybe -- if set, valid QualificationUsers with userCompanyPersonalNumber are transmitted via SAP interface under this id 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 SchoolQualificationShort school shorthand -- must be unique per school and shorthand
SchoolQualificationName school name -- must be unique per school and name SchoolQualificationName school name -- must be unique per school and name
-- across all schools, only one qualification may be a driving licence: -- across all schools, only one qualification may be a driving licence -- NO LONGER TRUE
UniqueQualificationAvsLicence avsLicence !force -- either empty or unique -- UniqueQualificationAvsLicence avsLicence !force -- either empty or unique
-- NOTE: two NULL values are not equal for the purpose of Uniqueness constraints! -- NOTE: two NULL values are not equal for the purpose of Uniqueness constraints!
deriving Eq Generic deriving Show Eq Generic Binary
-- TODOs: -- TODOs:
-- - Enstehen Kosten, wenn Teilnehmer für KnowHow eingereiht werden, aber nicht am Kurs teilnehmen? -- - 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 -- - PinReset==1 mit bestehendem Passwort kann problemlos erneut gesendet werden
-- - Flag "interner Mitarbeiter" wird von Know-How ignoriert / nicht ausgewertet (legacy) -- - 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 -- 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 -- qualification QualificationId OnDeleteCascade OnUpdateCascade -- AND: not unique, ie. qualification can have multiple required preconditions
required [QualificationId] -- OR : alternatives, any one will suffice -- required [QualificationId] -- OR : alternatives, any one will suffice -- we don't want array, since we have recursive CTEs
continuous Bool -- expiring precondition blocks qualification -- continuous Bool -- expiring precondition blocks qualification
deriving Generic -- deriving Generic Show
-- Maybe an alternative for online qualification validity checking, transitivity through recursive CTEs? (already available in our version) -- Maybe an alternative for online qualification validity checking, transitivity through recursive CTEs? (already available in our version)
-- QualificationRequirement QualificationRequirement
-- qualification QualificationId OnDeleteCascade OnUpdateCascade qualification QualificationId OnDeleteCascade OnUpdateCascade
-- requirement QualificationId OnDeleteCascade OnUpdateCascade requirement QualificationId OnDeleteCascade OnUpdateCascade
-- group Text -- OR: several requirements within the same group are considered equivalent group Int -- OR: several requirements within the same group are considered equivalent; no order between groups
-- UniqueQualificationRequirement qualification requirement note Text -- for humans only, no semantical effect
-- UniqueQualificationRequirement qualification requirement
deriving Generic Show
-- TODO: connect Qualification with Exams! -- TODO: connect Qualification with Exams!
@ -60,7 +63,7 @@ QualificationEdit
user UserId user UserId
time UTCTime time UTCTime
qualification QualificationId OnDeleteCascade OnUpdateCascade qualification QualificationId OnDeleteCascade OnUpdateCascade
deriving Generic deriving Generic Show
QualificationUser QualificationUser
user UserId OnDeleteCascade OnUpdateCascade user UserId OnDeleteCascade OnUpdateCascade
@ -69,11 +72,11 @@ QualificationUser
lastRefresh Day -- lastRefresh > validUntil possible, if Qualification^elearningOnly == False lastRefresh Day -- lastRefresh > validUntil possible, if Qualification^elearningOnly == False
firstHeld Day -- first time the qualification was earned, should never change 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 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 -- Reasons and temporary revocations are implemented through QualificationUserBlock
-- TODO: adjust SAP interface to transmit end dates -- TODO: adjust SAP interface to transmit end dates
UniqueQualificationUser qualification user UniqueQualificationUser qualification user
deriving Generic deriving Generic Show
QualificationUserBlock QualificationUserBlock
qualificationUser QualificationUserId OnDeleteCascade OnUpdateCascade 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. -- 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! 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 UniqueLmsQualificationUser qualification user -- each user may be enrolled at most once per course
deriving Generic deriving Generic Show
-- LmsUserStatus -- LmsUserStatus
-- lmsUser LmsUserId OnDeleteCascade OnUpdateCascade -- lmsUser LmsUserId OnDeleteCascade OnUpdateCascade
@ -148,7 +151,7 @@ LmsReport
lock Bool -- (0|1) lock Bool -- (0|1)
timestamp UTCTime default=now() timestamp UTCTime default=now()
UniqueLmsReport qualification ident -- required by DBTable UniqueLmsReport qualification ident -- required by DBTable
deriving Generic deriving Generic Show
-- LmsAudit removed by commit 71cde92a -- LmsAudit removed by commit 71cde92a
-- due to frequent transmit errors, a separate lms tranmission log is necessary again -- due to frequent transmit errors, a separate lms tranmission log is necessary again
@ -160,4 +163,16 @@ LmsReportLog
lock Bool -- (0|1) lock Bool -- (0|1)
timestamp UTCTime default=now() timestamp UTCTime default=now()
missing Bool default=false 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 created UTCTime
acknowledged UTCTime Maybe acknowledged UTCTime Maybe
recipient UserId Maybe OnDeleteSetNull OnUpdateCascade -- optional as some letters may contain just an address 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 sender UserId Maybe OnDeleteSetNull OnUpdateCascade -- senders and associations are optional
course CourseId Maybe OnDeleteCascade OnUpdateCascade course CourseId Maybe OnDeleteCascade OnUpdateCascade
qualification QualificationId Maybe OnDeleteCascade OnUpdateCascade qualification QualificationId Maybe OnDeleteCascade OnUpdateCascade
lmsUser LmsIdent Maybe OnDeleteSetNull OnUpdateCascade -- allows tracking if recipient has been notified; must be unique 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! -- 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 -- 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 PrintAcknowledge -- just to store acknowledging requests to be evaluated by a background job later on
apcIdent Text apcIdent Text
timestamp UTCTime default=now() timestamp UTCTime default=now()
processed Bool processed Bool
deriving Generic deriving Generic Show
PrintAckIdAlias PrintAckIdAlias
needle Text needle Text
replacement Text replacement Text
priority Int priority Int
deriving Generic deriving Generic Show

View File

@ -6,10 +6,9 @@ Tutorial json
name TutorialName name TutorialName
course CourseId OnDeleteCascade OnUpdateCascade course CourseId OnDeleteCascade OnUpdateCascade
type (CI Text) -- "Tutorium", "Zentralübung", ... type (CI Text) -- "Tutorium", "Zentralübung", ...
capacity Int Maybe -- limit for enrolment in this tutorial capacity Int Maybe -- limit for enrolment in this tutorial
room RoomReference Maybe
roomHidden Bool default=false roomHidden Bool default=false
time Occurrences time (JSONB Occurrences)
regGroup (CI Text) Maybe -- each participant may register for one tutorial per regGroup regGroup (CI Text) Maybe -- each participant may register for one tutorial per regGroup
registerFrom UTCTime Maybe registerFrom UTCTime Maybe
registerTo UTCTime Maybe registerTo UTCTime Maybe
@ -25,8 +24,19 @@ Tutor
UniqueTutor tutorial user UniqueTutor tutorial user
deriving Generic deriving Generic
TutorialParticipant TutorialParticipant
tutorial TutorialId OnDeleteCascade OnUpdateCascade tutorial TutorialId OnDeleteCascade OnUpdateCascade
user UserId user UserId
company CompanyId Maybe
drivingPermit UserDrivingPermit Maybe
eyeExam UserEyeExam Maybe
note Text Maybe
UniqueTutorialParticipant tutorial user UniqueTutorialParticipant tutorial user
deriving Eq Ord Show deriving Eq Ord Show Generic
deriving 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 -- 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. 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' surname UserSurname -- Display user names always through 'nameWidget displayName surname'
displayName UserDisplayName displayName UserDisplayName
displayEmail UserEmail 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 sending TODO: make this nullable 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 ident UserIdent -- Case-insensitive user-identifier. Defaults to "AVSID:dddddddd" if unknown
authentication AuthenticationMode -- 'AuthLDAP' or ('AuthPWHash'+password-hash) authentication AuthenticationMode -- 'AuthLDAP' or ('AuthPWHash'+password-hash)
lastAuthentication UTCTime Maybe -- last login date lastAuthentication UTCTime Maybe -- last login date
created UTCTime default=now() created UTCTime default=now()
lastLdapSynchronisation UTCTime Maybe 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) 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! matrikelnummer UserMatriculation Maybe -- usually a number; AVS Personalnummer; nicht Fraport Personalnummer!
firstName Text -- For export in tables, pre-split firstName from displayName 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 mobile Text Maybe
companyPersonalNumber Text Maybe -- Company will become a new table, but if company=fraport, some information is received via LDAP 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 companyDepartment Text Maybe -- thus we store such information for ease of reference directly, if available
pinPassword Text Maybe -- used to encrypt pins within emails pinPassword Text Maybe -- used to encrypt pins within emails, defaults to cardno.version
postAddress StoredMarkup Maybe 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 postLastUpdate UTCTime Maybe -- record postal address updates
prefersPostal Bool default=false -- user prefers letters by post instead of email 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 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 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 function SchoolFunction
UniqueUserFunction user school function UniqueUserFunction user school function
deriving Generic deriving Generic
UserSystemFunction UserSystemFunction Show
user UserId user UserId
function SystemFunction -- Defined in Model.Types.User function SystemFunction -- Defined in Model.Types.User
manual Bool -- Inserted manually by Admin or automatic from LDAP manual Bool -- Inserted manually by Admin or automatic from LDAP
isOptOut Bool -- User has currently deactivate the role for themselves isOptOut Bool -- User has currently deactivate the role for themselves
UniqueUserSystemFunction user function UniqueUserSystemFunction user function
deriving Generic deriving Generic Show
UserExamOffice UserExamOffice
user UserId user UserId
field StudyTermsId field StudyTermsId
UniqueUserExamOffice user field UniqueUserExamOffice user field
deriving Generic deriving Generic Show
UserSchool -- Managed by users themselves, encodes "schools of interest" UserSchool -- Managed by users themselves, encodes "schools of interest"
user UserId user UserId
school SchoolId school SchoolId
isOptOut Bool -- true if this a marker, that the user manually deleted this entry; it should not be recreated automatically isOptOut Bool -- true if this a marker, that the user manually deleted this entry; it should not be recreated automatically
UniqueUserSchool user school UniqueUserSchool user school
deriving Generic deriving Generic Show
UserGroupMember UserGroupMember
group UserGroupName group UserGroupName
user UserId user UserId
primary Checkmark nullable primary Checkmark nullable
UniquePrimaryUserGroupMember group primary !force UniquePrimaryUserGroupMember group primary !force
UniqueUserGroupMember group user UniqueUserGroupMember group user
deriving Generic deriving Generic Show
UserCompany UserCompany
user UserId user UserId
company CompanyId OnDeleteCascade OnUpdateCascade company CompanyId OnDeleteCascade OnUpdateCascade
supervisor Bool default=false -- should this user be made supervisor for all _new_ users associated with this company? 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? 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 UniqueUserCompany user company -- a user may belong to multiple companies, but to each one only once
deriving Generic deriving Generic Show
UserSupervisor UserSupervisor
supervisor UserId -- multiple supervisor per trainee possible supervisor UserId -- multiple supervisor per trainee possible
user UserId user UserId
rerouteNotifications Bool -- User can be his own supervisor to receive notifications as well 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) company CompanyId Maybe OnDeleteCascade OnUpdateCascade -- this supervisor was company default supervisor at time of entry
deriving Generic 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", "name": "fradrive",
"version": "27.4.59", "version": "27.5.1",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "fradrive", "name": "fradrive",
"version": "27.4.59", "version": "27.5.1",
"license": "AGPL-3.0-or-later", "license": "AGPL-3.0-or-later",
"dependencies": { "dependencies": {
"@babel/runtime": "^7.25.6", "@babel/runtime": "^7.25.6",
@ -68,7 +68,6 @@
"karma-browserify": "^8.1.0", "karma-browserify": "^8.1.0",
"karma-chrome-launcher": "^3.2.0", "karma-chrome-launcher": "^3.2.0",
"karma-cli": "^2.0.0", "karma-cli": "^2.0.0",
"karma-esbuild": "^2.3.0",
"karma-jasmine": "^5.1.0", "karma-jasmine": "^5.1.0",
"karma-jasmine-html-reporter": "^2.1.0", "karma-jasmine-html-reporter": "^2.1.0",
"karma-mocha-reporter": "^2.2.5", "karma-mocha-reporter": "^2.2.5",
@ -5815,9 +5814,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/cookie": { "node_modules/cookie": {
"version": "0.7.2", "version": "0.4.2",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz",
"integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@ -5983,9 +5982,9 @@
} }
}, },
"node_modules/cross-spawn": { "node_modules/cross-spawn": {
"version": "7.0.6", "version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -6879,9 +6878,9 @@
"license": "ISC" "license": "ISC"
}, },
"node_modules/elliptic": { "node_modules/elliptic": {
"version": "6.6.1", "version": "6.5.7",
"resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.1.tgz", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.7.tgz",
"integrity": "sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==", "integrity": "sha512-ESVCtTwiA+XhY3wyh24QqRGBoP3rEdDUl3EDUUo9tft074fi19IrdpH7hLCMMP3CIj7jb3W96rn8lt/BqIlt5Q==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -6939,9 +6938,9 @@
} }
}, },
"node_modules/engine.io": { "node_modules/engine.io": {
"version": "6.6.2", "version": "6.5.5",
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.2.tgz", "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.5.tgz",
"integrity": "sha512-gmNvsYi9C8iErnZdVcJnvCpSKbWTt1E8+JZo8b+daLninywUWi5NQ5STSHZ9rFjFO7imNcvb8Pc5pe/wMR5xEw==", "integrity": "sha512-C5Pn8Wk+1vKBoHghJODM63yk8MvrO9EWZUfkAt5HAqIgPE4/8FF0PEGHXtEd40l223+cE5ABWuPzm38PHFXfMA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -6950,7 +6949,7 @@
"@types/node": ">=10.0.0", "@types/node": ">=10.0.0",
"accepts": "~1.3.4", "accepts": "~1.3.4",
"base64id": "2.0.0", "base64id": "2.0.0",
"cookie": "~0.7.2", "cookie": "~0.4.1",
"cors": "~2.8.5", "cors": "~2.8.5",
"debug": "~4.3.1", "debug": "~4.3.1",
"engine.io-parser": "~5.2.1", "engine.io-parser": "~5.2.1",
@ -10114,20 +10113,6 @@
"node": ">= 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": { "node_modules/karma-jasmine": {
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-5.1.0.tgz", "resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-5.1.0.tgz",
@ -10940,9 +10925,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/nanoid": { "node_modules/nanoid": {
"version": "3.3.8", "version": "3.3.7",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
"integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
"dev": true, "dev": true,
"funding": [ "funding": [
{ {
@ -11226,9 +11211,9 @@
} }
}, },
"node_modules/npm-run-all/node_modules/cross-spawn": { "node_modules/npm-run-all/node_modules/cross-spawn": {
"version": "6.0.6", "version": "6.0.5",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.6.tgz", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
"integrity": "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==", "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -16946,9 +16931,9 @@
} }
}, },
"node_modules/socket.io": { "node_modules/socket.io": {
"version": "4.8.1", "version": "4.7.5",
"resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.1.tgz", "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.5.tgz",
"integrity": "sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg==", "integrity": "sha512-DmeAkF6cwM9jSfmp6Dr/5/mfMwb5Z5qRrSXLpo3Fq5SqyU8CMF15jIN4ZhfSwu35ksM1qmHZDQ/DK5XTccSTvA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -16956,7 +16941,7 @@
"base64id": "~2.0.0", "base64id": "~2.0.0",
"cors": "~2.8.5", "cors": "~2.8.5",
"debug": "~4.3.2", "debug": "~4.3.2",
"engine.io": "~6.6.0", "engine.io": "~6.5.2",
"socket.io-adapter": "~2.5.2", "socket.io-adapter": "~2.5.2",
"socket.io-parser": "~4.2.4" "socket.io-parser": "~4.2.4"
}, },

View File

@ -1,6 +1,6 @@
{ {
"name": "fradrive", "name": "fradrive",
"version": "27.4.59", "version": "27.5.1",
"description": "", "description": "",
"keywords": [], "keywords": [],
"author": "", "author": "",
@ -54,7 +54,6 @@
"karma-browserify": "^8.1.0", "karma-browserify": "^8.1.0",
"karma-chrome-launcher": "^3.2.0", "karma-chrome-launcher": "^3.2.0",
"karma-cli": "^2.0.0", "karma-cli": "^2.0.0",
"karma-esbuild": "^2.3.0",
"karma-jasmine": "^5.1.0", "karma-jasmine": "^5.1.0",
"karma-jasmine-html-reporter": "^2.1.0", "karma-jasmine-html-reporter": "^2.1.0",
"karma-mocha-reporter": "^2.2.5", "karma-mocha-reporter": "^2.2.5",
@ -90,9 +89,6 @@
}, },
"scripts": { "scripts": {
"build": "node esbuild.config.mjs", "build": "node esbuild.config.mjs",
"start": "node esbuild.config.mjs --watch", "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\""
} }
} }

View File

@ -3,7 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
name: uniworx name: uniworx
version: 27.4.59 version: 27.5.1
dependencies: dependencies:
- base - base
- yesod - 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 -- SPDX-License-Identifier: AGPL-3.0-or-later
@ -53,11 +53,12 @@
/ NewsR GET !free / NewsR GET !free
/users UsersR GET POST -- no tags, i.e. admins only /users UsersR GET POST -- no tags, i.e. admins only
/users/#CryptoUUIDUser AdminUserR GET POST /users/#CryptoUUIDUser AdminUserR GET POST
/users/#CryptoUUIDUser/delete AdminUserDeleteR POST /users/#CryptoUUIDUser/delete AdminUserDeleteR POST
/users/#CryptoUUIDUser/hijack AdminHijackUserR GET POST !adminANDno-escalation /users/#CryptoUUIDUser/hijack AdminHijackUserR GET POST !adminANDno-escalation
/users/#CryptoUUIDUser/notifications UserNotificationR GET POST !self /users/#CryptoUUIDUser/notifications UserNotificationR GET POST !self
/users/#CryptoUUIDUser/password UserPasswordR GET POST !selfANDis-pw-hash /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/new AdminNewFunctionaryInviteR GET POST
!/users/functionary-invite AdminFunctionaryInviteR GET POST !/users/functionary-invite AdminFunctionaryInviteR GET POST
!/users/add AdminUserAddR GET POST !/users/add AdminUserAddR GET POST
@ -69,14 +70,21 @@
/admin/crontab AdminCrontabR GET /admin/crontab AdminCrontabR GET
/admin/crontab/jobs AdminJobsR GET POST /admin/crontab/jobs AdminJobsR GET POST
/admin/avs AdminAvsR GET POST /admin/avs AdminAvsR GET POST
/admin/avs/#CryptoUUIDUser AdminAvsUserR GET /admin/avs/#CryptoUUIDUser AdminAvsUserR GET POST
/admin/ldap AdminLdapR GET POST /admin/ldap AdminLdapR GET POST
/admin/problems AdminProblemsR GET /admin/problems AdminProblemsR GET POST
/admin/problems/no-contact ProblemUnreachableR GET /admin/problems/no-contact ProblemUnreachableR GET POST
/admin/problems/no-avs-id ProblemWithoutAvsId GET /admin/problems/no-avs-id ProblemWithoutAvsId GET
/admin/problems/r-without-f ProblemFbutNoR GET /admin/problems/r-without-f ProblemFbutNoR GET
/admin/problems/avs ProblemAvsSynchR GET POST /admin/problems/avs ProblemAvsSynchR GET POST
/admin/problems/avs/errors ProblemAvsErrorR GET /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 PrintCenterR GET POST !system-printer
/print/acknowledge/#Day/#Int/#Int PrintAckR 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 FirmAllR GET POST -- not yet !supervisor
/firms/comm/+Companies FirmsCommR GET POST /firms/comm/+Companies FirmsCommR GET POST
/firms/supervision FirmsSupervisionR GET POST
/firm/#CompanyShorthand/comm FirmCommR GET POST /firm/#CompanyShorthand/comm FirmCommR GET POST
/firm/#CompanyShorthand FirmUsersR GET POST -- not yet !supervisor /firm/#CompanyShorthand FirmUsersR GET POST -- not yet !supervisor
/firm/#CompanyShorthand/supers FirmSupersR GET POST -- not yet !supervisor /firm/#CompanyShorthand/supers FirmSupersR GET POST -- not yet !supervisor
@ -150,8 +159,9 @@
/school SchoolListR GET /school SchoolListR GET
!/school/new SchoolNewR GET POST !/school/new SchoolNewR GET POST
/school/#SchoolId SchoolR: /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 ParticipantsListR GET !evaluation
/participants/#TermId/#SchoolId ParticipantsR GET !evaluation /participants/#TermId/#SchoolId ParticipantsR GET !evaluation
@ -221,6 +231,7 @@
/delete TDeleteR GET POST /delete TDeleteR GET POST
/participants TUsersR GET POST !tutor /participants TUsersR GET POST !tutor
/participants/add TAddUserR GET POST !tutor /participants/add TAddUserR GET POST !tutor
/participants/exam/#ExamName TExamR GET POST !tutor
/register TRegisterR POST !timeANDcapacityANDcourse-registeredANDregister-group !timeANDtutorial-registered /register TRegisterR POST !timeANDcapacityANDcourse-registeredANDregister-group !timeANDtutorial-registered
/communication TCommR GET POST !tutor /communication TCommR GET POST !tutor
/tutor-invite TInviteR GET POST !tutorANDtutor-control /tutor-invite TInviteR GET POST !tutorANDtutor-control
@ -270,20 +281,22 @@
!/#UUID CryptoUUIDDispatchR GET !free -- just redirect !/#UUID CryptoUUIDDispatchR GET !free -- just redirect
-- !/*{CI FilePath} CryptoFileNameDispatchR GET !free -- Disabled until preliminary check for valid cID exists -- !/*{CI FilePath} CryptoFileNameDispatchR GET !free -- Disabled until preliminary check for valid cID exists
/qualification QualificationAllR GET !free /qualification QualificationAllR GET !free
/qualification/#SchoolId QualificationSchoolR GET !free /qualification/#SchoolId QualificationSchoolR GET !free
/qualification/#SchoolId/#QualificationShorthand QualificationR GET POST !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 -- /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
/lms LmsAllR GET POST /lms LmsAllR GET POST
/lms/#SchoolId LmsSchoolR GET /lms/#SchoolId LmsSchoolR GET
/lms/#SchoolId/#QualificationShorthand LmsR GET POST /lms/#SchoolId/#QualificationShorthand LmsR GET POST
/lms/#SchoolId/#QualificationShorthand/edit LmsEditR GET POST
-- new V2 LMS Interface -- new V2 LMS Interface
/lms/#SchoolId/#QualificationShorthand/learners LmsLearnersR GET /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/learners/direct LmsLearnersDirectR GET !token -- LMS
/lms/#SchoolId/#QualificationShorthand/report LmsReportR GET POST /lms/#SchoolId/#QualificationShorthand/report LmsReportR GET POST
/lms/#SchoolId/#QualificationShorthand/report/upload LmsReportUploadR 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 # busybox # for print services, but interferes with build commands in develop-shell
htop htop
pdftk # pdftk just for testing pdf-passwords pdftk # pdftk just for testing pdf-passwords
roboto roboto-mono
# texlive.combined.scheme-full # works # texlive.combined.scheme-full # works
# texlive.combined.scheme-medium # texlive.combined.scheme-medium
# texlive.combined.scheme-small # texlive.combined.scheme-small
(texlive.combine { (texlive.combine {
inherit (texlive) scheme-basic inherit (texlive) scheme-basic
babel-german babel-english booktabs textpos 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 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 -- SPDX-License-Identifier: AGPL-3.0-or-later
@ -115,16 +115,11 @@ import GHC.RTS.Flags (getRTSFlags)
import qualified Prometheus import qualified Prometheus
import qualified Data.IntervalMap.Strict as IntervalMap
import qualified Utils.Pool as Custom import qualified Utils.Pool as Custom
import Utils.Postgresql
import Handler.Utils.Memcached (manageMemcachedLocalInvalidations)
import qualified System.Clock as Clock import qualified System.Clock as Clock
import Utils.Avs import Utils.Avs (mkAvsQuery)
-- Import all relevant handler modules here. -- Import all relevant handler modules here.
-- (HPack takes care to add new modules to our cabal file nowadays.) -- (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.Admin
import Handler.Term import Handler.Term
import Handler.School import Handler.School
import Handler.School.DayTasks
import Handler.Course import Handler.Course
import Handler.Sheet import Handler.Sheet
import Handler.Submission import Handler.Submission
@ -157,6 +153,8 @@ import Handler.Upload
import Handler.Qualification import Handler.Qualification
import Handler.LMS import Handler.LMS
import Handler.SAP import Handler.SAP
import Handler.CommCenter
import Handler.MailCenter
import Handler.PrintCenter import Handler.PrintCenter
import Handler.ApiDocs import Handler.ApiDocs
import Handler.Swagger import Handler.Swagger
@ -216,18 +214,6 @@ makeFoundation appSettings''@AppSettings{..} = do
appJobState <- liftIO newEmptyTMVarIO appJobState <- liftIO newEmptyTMVarIO
appHealthReport <- liftIO $ newTVarIO Set.empty 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 appStartTime <- liftIO getCurrentTime
-- We need a log function to create a connection pool. We need a connection -- 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 -- 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. -- from there, and then create the real foundation.
let let
mkFoundation :: _ -> (forall m. MonadIO m => Custom.Pool' m DBConnLabel DBConnUseState SqlBackend) -> _ 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 tempFoundation = mkFoundation
(error "appSettings' forced in tempFoundation") (error "appSettings' forced in tempFoundation")
(error "connPool forced in tempFoundation") (error "connPool forced in tempFoundation")
@ -249,7 +235,6 @@ makeFoundation appSettings''@AppSettings{..} = do
(error "JSONWebKeySet forced in tempFoundation") (error "JSONWebKeySet forced in tempFoundation")
(error "ClusterID forced in tempFoundation") (error "ClusterID forced in tempFoundation")
(error "memcached forced in tempFoundation") (error "memcached forced in tempFoundation")
(error "memcachedLocal forced in tempFoundation")
(error "MinioConn forced in tempFoundation") (error "MinioConn forced in tempFoundation")
(error "VerpSecret forced in tempFoundation") (error "VerpSecret forced in tempFoundation")
(error "AuthKey forced in tempFoundation") (error "AuthKey forced in tempFoundation")
@ -334,12 +319,6 @@ makeFoundation appSettings''@AppSettings{..} = do
$logWarnS "setup" "Clearing memcached" $logWarnS "setup" "Clearing memcached"
liftIO $ Memcached.flushAll memcachedConn liftIO $ Memcached.flushAll memcachedConn
return AppMemcached{..} 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 appSessionStore <- mkSessionStore appSettings'' sqlPool `customRunSqlPool` sqlPool
@ -352,15 +331,15 @@ makeFoundation appSettings''@AppSettings{..} = do
handleIf isBucketExists (const $ return ()) $ Minio.makeBucket appUploadTmpBucket Nothing handleIf isBucketExists (const $ return ()) $ Minio.makeBucket appUploadTmpBucket Nothing
return conn return conn
appAvsQuery <- case appAvsConf of appAvsQuery <- case appAvsConf of
Nothing -> do Nothing -> do
$logErrorS "avsPrepare" "appAvsConfig is empty, i.e. invalid AVS configuration settings." $logErrorS "avsPrepare" "appAvsConfig is empty, i.e. invalid AVS configuration settings."
return Nothing return Nothing
-- error "AvsConfig is empty, i.e. invalid AVS configuration settings." -- error "AvsConfig is empty, i.e. invalid AVS configuration settings."
Just avsConf -> do Just avsConf -> do
manager <- newManagerSettings $ mkManagerSettings (def { settingDisableCertificateValidation = True }) Nothing manager <- newManagerSettings $ mkManagerSettings (def { settingDisableCertificateValidation = True }) Nothing
let avsServer = BaseUrl let avsServer = BaseUrl
{ baseUrlScheme = Https { baseUrlScheme = Https
, baseUrlHost = avsHost avsConf , baseUrlHost = avsHost avsConf
, baseUrlPort = avsPort avsConf , baseUrlPort = avsPort avsConf
@ -377,7 +356,7 @@ makeFoundation appSettings''@AppSettings{..} = do
$logDebugS "Runtime configuration" $ tshowCrop appSettings' $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 -- Return the foundation
$logInfoS "setup" "*** DONE ***" $logInfoS "setup" "*** DONE ***"
@ -657,7 +636,7 @@ appMain = runResourceT $ do
notifyWatchdog = forever' Nothing $ \pResults -> do notifyWatchdog = forever' Nothing $ \pResults -> do
let delay = floor $ wInterval % 4 let delay = floor $ wInterval % 4
d <- liftIO $ newDelay delay d <- liftIO $ newDelay delay
$logDebugS "Notify" $ "Waiting up to " <> tshow delay <> "µs..." $logDebugS "Notify" $ "Waiting up to " <> tshow delay <> "µs..."
mResults <- atomically $ asum mResults <- atomically $ asum
[ pResults <$ waitDelay d [ pResults <$ waitDelay d
@ -746,8 +725,8 @@ shutdownApp app = do
-- | Run a handler -- | Run a handler
handler, handler' :: Handler a -> IO a handler, handler' :: Handler a -> IO a
handler h = runResourceT $ getAppDevSettings >>= makeFoundation >>= liftIO . flip unsafeHandler h handler h = runResourceT $ getAppDevSettings >>= makeFoundation >>= liftIO . flip unsafeHandler h
handler' h = runResourceT $ getAppSettings >>= makeFoundation >>= liftIO . flip unsafeHandler h handler' h = runResourceT $ getAppSettings >>= makeFoundation >>= liftIO . flip unsafeHandler h
-- | Run DB queries -- | Run DB queries
db, db' :: DB a -> IO a 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 -- SPDX-License-Identifier: AGPL-3.0-or-later
{-# LANGUAGE TypeApplications #-}
module Audit module Audit
( module Audit.Types ( module Audit.Types
, AuditException(..) , AuditException(..)
@ -9,6 +11,7 @@ module Audit
, AuditRemoteException(..) , AuditRemoteException(..)
, getRemote , getRemote
, logInterface, logInterface' , logInterface, logInterface'
, reportAdminProblem
) where ) where
@ -16,6 +19,8 @@ import Import.NoModel
import Settings import Settings
import Model import Model
import Database.Persist.Sql 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 Audit.Types
import qualified Data.Text as Text import qualified Data.Text as Text
@ -128,7 +133,7 @@ logInterface :: ( AuthId (HandlerSite m) ~ Key User
-> Text -- ^ Any additional information -> Text -- ^ Any additional information
-> ReaderT (YesodPersistBackend (HandlerSite m)) m () -> ReaderT (YesodPersistBackend (HandlerSite m)) m ()
-- ^ Log a transaction using information available from `HandlerT`, also calls `audit` -- ^ 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 interfaceLogWrite <- (methodGet /=) . Wai.requestMethod . reqWaiRequest <$> getRequest
logInterface' interfaceLogInterface interfaceLogSubtype interfaceLogWrite interfaceLogSuccess interfaceLogRows interfaceLogInfo 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` -- ^ 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 logInterface' (Text.strip -> interfaceLogInterface) (Text.strip -> interfaceLogSubtype) interfaceLogWrite interfaceLogSuccess interfaceLogRows (Text.strip -> interfaceLogInfo) = do
interfaceLogTime <- liftIO getCurrentTime 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{..} -- insert_ InterfaceLog{..}
void $ upsertBy (UniqueInterfaceSubtypeWrite interfaceLogInterface interfaceLogSubtype interfaceLogWrite) void $ upsertBy (UniqueInterfaceSubtypeWrite interfaceLogInterface interfaceLogSubtype interfaceLogWrite)
( InterfaceLog{..} ) ( InterfaceLog{..} )
@ -169,3 +174,28 @@ logInterface' (Text.strip -> interfaceLogInterface) (Text.strip -> interfaceLogS
, transactionInterfaceInfo = interfaceLogInfo , transactionInterfaceInfo = interfaceLogInfo
, transactionInterfaceSuccess = Just interfaceLogSuccess , 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 -- SPDX-License-Identifier: AGPL-3.0-or-later
module Audit.Types module Audit.Types
( Transaction(..) ( Transaction(..)
, AdminProblem(..)
, decodeAdminProblem
) where ) where
import ClassyPrelude.Yesod hiding (derivePersistFieldJSON) import ClassyPrelude.Yesod hiding (derivePersistFieldJSON)
import Model.Types.TH.JSON import Model.Types.TH.JSON
import Model import Model
import Data.Aeson
import Data.Aeson.TH import Data.Aeson.TH
import Utils.PathPiece import Utils.PathPiece
@ -182,7 +185,7 @@ data Transaction
} }
| TransactionLmsStart | TransactionLmsStart
{ transactionQualification :: QualificationId { transactionQualification :: QualificationId
, transactionLmsIdent :: LmsIdent , transactionLmsIdent :: LmsIdent
, transactionLmsUser :: UserId , transactionLmsUser :: UserId
, transactionLmsUserKey :: LmsUserId , transactionLmsUserKey :: LmsUserId
} }
@ -210,10 +213,16 @@ data Transaction
, transactionNote :: Maybe Text , transactionNote :: Maybe Text
, transactionReceived :: UTCTime -- when was the csv file received? , 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! | TransactionQualificationUserEdit -- Note that a renewal always entails unblocking as well!
{ transactionUser :: UserId -- qualification holder that is updated { transactionUser :: UserId -- qualification holder that is updated
, transactionQualificationUser :: QualificationUserId -- not really necessary, maybe remove? , transactionQualificationUser :: QualificationUserId -- not really necessary, maybe remove?
, transactionQualification :: QualificationId , transactionQualification :: QualificationId
, transactionQualificationValidUntil :: Day , transactionQualificationValidUntil :: Day
, transactionQualificationScheduleRenewal :: Maybe Bool -- Maybe, because some update may leave it unchanged (also avoids DB Migration) , transactionQualificationScheduleRenewal :: Maybe Bool -- Maybe, because some update may leave it unchanged (also avoids DB Migration)
, transactionNote :: Maybe Text , transactionNote :: Maybe Text
@ -251,4 +260,64 @@ deriveJSON defaultOptions
, sumEncoding = TaggedObject "transaction" "data" , sumEncoding = TaggedObject "transaction" "data"
} ''Transaction } ''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 mr <- getMessageRender
wreq (ciField & addDatalist userList) (fslpI MsgDummyIdent (mr MsgDummyIdentPlaceholder) & addAttr "autocomplete" "username" & addName PostLoginDummy) Nothing wreq (ciField & addDatalist userList) (fslpI MsgDummyIdent (mr MsgDummyIdentPlaceholder) & addAttr "autocomplete" "username" & addName PostLoginDummy) Nothing
where 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) toOption (Entity _ User{..}) = Option userDisplayName userIdent (CI.original userIdent)
apDummy :: Text apDummy :: Text

View File

@ -1,7 +1,6 @@
-- {-# LANGUAGE BangPatterns #-} {-# OPTIONS_GHC -Wwarn -fno-warn-orphans #-}
{-# OPTIONS_GHC -Wwarn #-}
-- 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 -- SPDX-License-Identifier: AGPL-3.0-or-later
@ -64,8 +63,9 @@ foreign import ccall unsafe "sodium_bin2hex"
bin2hex :: ByteString -> String bin2hex :: ByteString -> String
bin2hex bs = let tlen = S.length bs * 2 + 1 in bin2hex bs = let tlen = S.length bs * 2 + 1 in
S8.unpack . S8.init . snd . buildUnsafeByteString tlen $ \t -> S8.unpack . S8.init . snd . buildUnsafeByteString tlen $ \t ->
constByteStrings [bs] $ \[(pbs, _)] -> let aux [(pbs, _)] = c_sodium_bin2hex t (fromIntegral tlen) pbs (fromIntegral $ S.length bs)
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 instance Show Key where
show k = "SecretBox.Key {hashesTo = \"" <> (bin2hex . shorthash nullShKey $ encode k) <> "}\"" 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