From 960bd76acafc9cd077b831b67a281eb7b20e703c Mon Sep 17 00:00:00 2001 From: Sarah Vaupel Date: Tue, 1 Jun 2021 22:53:46 +0200 Subject: [PATCH] feat(schools): more school-wide configuration authorship statements --- .../categories/school/de-de-formal.msg | 12 +++-- messages/uniworx/categories/school/en-eu.msg | 12 +++-- models/authorship-statements.model | 17 +++++++ models/schools.model | 6 ++- models/sheets.model | 2 + src/Handler/School.hs | 47 ++++++++++++++----- src/Model/Migration/Definitions.hs | 3 ++ test/Database/Fill.hs | 5 +- 8 files changed, 79 insertions(+), 25 deletions(-) create mode 100644 models/authorship-statements.model diff --git a/messages/uniworx/categories/school/de-de-formal.msg b/messages/uniworx/categories/school/de-de-formal.msg index d4feac656..88f5088f1 100644 --- a/messages/uniworx/categories/school/de-de-formal.msg +++ b/messages/uniworx/categories/school/de-de-formal.msg @@ -20,11 +20,13 @@ SchoolAuthorshipStatementModeNone: Keine Eigenständigkeitserklärung erlauben SchoolAuthorshipStatementModeOptional: Eigenständigkeitserklärung optional einforderbar SchoolAuthorshipStatementModeRequired: Eigenständigkeitserklärung immer erforderlich SchoolSheetAuthorshipStatementMode: Modus für nicht-prüfungsrelevante Übungsblattabgaben -SchoolSheetAuthorshipStatementExamMode: Modus für prüfungsrelevante Übungsblattabgaben -SchoolSheetAuthorshipStatementText: Eigenständigkeitserklärung -SchoolSheetAuthorshipStatementTextTip: Dieser Text dient als Standard-Eigenständigkeitserklärung beim Anlegen eines neuen Übungsblattes innerhalb eines Kurses dieses Instituts. Wenn Anpassungen erlaubt sind, kann diese Erklärung pro Übungsblatt durch einen Dozierenden überschrieben werden. -SchoolSheetAuthorshipStatementAllowOther: Anpassungen erlauben? -SchoolSheetAuthorshipStatementAllowOtherTip: Soll es Dozierenden erlaubt sein, pro Übungsblatt eine abweichende Eigenständigkeitserklärung anzugeben? +SchoolSheetAuthorshipStatementDefinition: Eigenständigkeitserklärung für nicht-prüfungsrelevante Übungsblattabgaben +SchoolSheetAuthorshipStatementDefinitionTip: Deutsch und Englisch +SchoolSheetAuthorshipStatementAllowOther: Abweichende Erklärungen für nicht-prüfungsrelevante Übungsblätter erlauben? +SchoolSheetExamAuthorshipStatementMode: Modus für prüfungsrelevante Übungsblattabgaben +SchoolSheetExamAuthorshipStatementDefinition: Eigenständigkeitserklärung für prüfungsrelevante Übungsblattabgaben +SchoolSheetExamAuthorshipStatementDefinitionTip: Deutsch und Englisch +SchoolSheetExamAuthorshipStatementAllowOther: Abweichende Erklärungen für prüfungsrelevante Übungsblätter erlauben? SchoolUpdated ssh@SchoolId: #{ssh} erfolgreich angepasst SchoolTitle ssh@SchoolId: Institut „#{ssh}“ diff --git a/messages/uniworx/categories/school/en-eu.msg b/messages/uniworx/categories/school/en-eu.msg index aa7d295fc..16b256eef 100644 --- a/messages/uniworx/categories/school/en-eu.msg +++ b/messages/uniworx/categories/school/en-eu.msg @@ -20,11 +20,13 @@ SchoolAuthorshipStatementModeNone: No Statement of Authorship allowed SchoolAuthorshipStatementModeOptional: Statement of Authorship optionally activatable SchoolAuthorshipStatementModeRequired: Statement of Authorship always required SchoolSheetAuthorshipStatementMode: Mode for exam-unrelated exercise sheets -SchoolSheetAuthorshipStatementExamMode: Mode for exam-related sheets -SchoolSheetAuthorshipStatementText: Statement of Authorship -SchoolSheetAuthorshipStatementTextTip: This text serves as default Statement of Authorship upon creating a new exercise sheet in a course of this school. This statement may be overriden by a course administrator per exercise sheet if adaptations are allowed. -SchoolSheetAuthorshipStatementAllowOther: Allow adaptations? -SchoolSheetAuthorshipStatementAllowOtherTip: Should course administrators be allowed to specify an alternative Statement of Authorship? +SchoolSheetAuthorshipStatementDefinition: Statement of Authorship for exam-unrelated exercise sheets +SchoolSheetAuthorshipStatementDefinitionTip: German and English +SchoolSheetAuthorshipStatementAllowOther: Allow adaptations for exam-unrelated exercise sheets? +SchoolSheetExamAuthorshipStatementMode: Mode for exam-related exercise sheets +SchoolSheetExamAuthorshipStatementDefinition: Statement of Authorship for exam-related exercise sheets +SchoolSheetExamAuthorshipStatementDefinitionTip: German and English +SchoolSheetExamAuthorshipStatementAllowOther: Allow adaptations for exam-related exercise sheets? SchoolUpdated ssh: Successfully edited #{ssh} SchoolTitle ssh: Department „#{ssh}“ diff --git a/models/authorship-statements.model b/models/authorship-statements.model new file mode 100644 index 000000000..184071798 --- /dev/null +++ b/models/authorship-statements.model @@ -0,0 +1,17 @@ +AuthorshipStatementDefinition + content StoredMarkup -- must contain statements in all relevant languages for now, TODO: refactor (use translations as below) + deriving Generic +-- AuthorshipStatementDefinitionTranslation +-- definition AuthorshipStatementDefinitionId +-- language Lang +-- content StoredMarkup +-- UniqueAuthorshipStatementDefinitionTranslation definition language +-- deriving Generic + +-- Statement of Authorship to be issued upon submitting a solution for an exercise sheet +-- TODO: maybe move to SubmissionUser? (With statementSigned :: Bool, statement :: Maybe StoredMarkup) +AuthorshipStatementSubmission + submissionUser SubmissionUserId + statement StoredMarkup -- stored as plain StoredMarkup as the "signed" statement needs to be persisted + UniqueAuthorshipStatementSubmission submissionUser + deriving Generic diff --git a/models/schools.model b/models/schools.model index 1db8cd10d..0c96091c9 100644 --- a/models/schools.model +++ b/models/schools.model @@ -9,9 +9,11 @@ School json examDiscouragedModes ExamModeDNF examCloseMode ExamCloseMode default='separate' sheetAuthorshipStatementMode SchoolAuthorshipStatementMode default='optional' - sheetAuthorshipStatementExamMode SchoolAuthorshipStatementMode default='optional' - sheetAuthorshipStatementText StoredMarkup Maybe + sheetAuthorshipStatementDefinition AuthorshipStatementDefinitionId Maybe sheetAuthorshipStatementAllowOther Bool default=true + sheetExamAuthorshipStatementMode SchoolAuthorshipStatementMode default='optional' + sheetExamAuthorshipStatementDefinition AuthorshipStatementDefinitionId Maybe + sheetExamAuthorshipStatementAllowOther Bool default=true UniqueSchool name UniqueSchoolShorthand shorthand -- required for Normalisation of CI Text Primary shorthand -- newtype Key School = SchoolKey { unSchoolKey :: SchoolShorthand } diff --git a/models/sheets.model b/models/sheets.model index 08073eed3..c4f622f84 100644 --- a/models/sheets.model +++ b/models/sheets.model @@ -15,6 +15,8 @@ Sheet -- exercise sheet for a given course anonymousCorrection Bool default=true requireExamRegistration ExamId Maybe -- Students may only submit if they are registered for the given exam allowNonPersonalisedSubmission Bool default=true +-- authorshipStatementRequired Bool default=false +-- authorshipStatementDefinition AuthorshipStatementDefinitionId Maybe CourseSheet course name deriving Generic SheetEdit -- who edited when a row in table "Course", kept indefinitely diff --git a/src/Handler/School.hs b/src/Handler/School.hs index f97d64097..9ce5c2748 100644 --- a/src/Handler/School.hs +++ b/src/Handler/School.hs @@ -69,9 +69,11 @@ data SchoolForm = SchoolForm , sfExamDiscouragedModes :: ExamModeDNF , sfExamCloseMode :: ExamCloseMode , sfSheetAuthorshipStatementMode :: SchoolAuthorshipStatementMode - , sfSheetAuthorshipStatementExamMode :: SchoolAuthorshipStatementMode - , sfSheetAuthorshipStatementText :: Maybe StoredMarkup + , sfSheetAuthorshipStatementDefinition :: Maybe StoredMarkup -- TODO: Must contain statements in all relevant languages for now; later use `Maybe (Map Lang StoredMarkup)` instead , sfSheetAuthorshipStatementAllowOther :: Bool + , sfSheetExamAuthorshipStatementMode :: SchoolAuthorshipStatementMode + , sfSheetExamAuthorshipStatementDefinition :: Maybe StoredMarkup -- TODO: Must contain statements in all relevant languages for now; later use `Maybe (Map Lang StoredMarkup)` instead + , sfSheetExamAuthorshipStatementAllowOther :: Bool } mkSchoolForm :: Maybe SchoolId -> Maybe SchoolForm -> Form SchoolForm @@ -87,9 +89,11 @@ mkSchoolForm mSsh template = renderAForm FormStandard $ SchoolForm <*> apopt (selectField optionsFinite) (fslI MsgExamCloseMode) (sfExamCloseMode <$> template <|> pure ExamCloseSeparate) <* aformSection MsgSchoolAuthorshipStatementSection <*> apopt (selectField optionsFinite) (fslI MsgSchoolSheetAuthorshipStatementMode) (sfSheetAuthorshipStatementMode <$> template <|> pure SchoolAuthorshipStatementModeOptional) - <*> apopt (selectField optionsFinite) (fslI MsgSchoolSheetAuthorshipStatementExamMode) (sfSheetAuthorshipStatementExamMode <$> template <|> pure SchoolAuthorshipStatementModeOptional) - <*> aopt htmlField (fslI MsgSchoolSheetAuthorshipStatementText & setTooltip MsgSchoolSheetAuthorshipStatementTextTip) (sfSheetAuthorshipStatementText <$> template) - <*> apopt checkBoxField (fslI MsgSchoolSheetAuthorshipStatementAllowOther & setTooltip MsgSchoolSheetAuthorshipStatementAllowOtherTip) (sfSheetAuthorshipStatementAllowOther <$> template <|> pure True) + <*> aopt htmlField (fslI MsgSchoolSheetAuthorshipStatementDefinition & setTooltip MsgSchoolSheetAuthorshipStatementDefinitionTip) (sfSheetAuthorshipStatementDefinition <$> template) + <*> apopt checkBoxField (fslI MsgSchoolSheetAuthorshipStatementAllowOther) (sfSheetAuthorshipStatementAllowOther <$> template <|> pure True) + <*> apopt (selectField optionsFinite) (fslI MsgSchoolSheetExamAuthorshipStatementMode) (sfSheetExamAuthorshipStatementMode <$> template <|> pure SchoolAuthorshipStatementModeOptional) + <*> aopt htmlField (fslI MsgSchoolSheetExamAuthorshipStatementDefinition & setTooltip MsgSchoolSheetExamAuthorshipStatementDefinitionTip) (sfSheetExamAuthorshipStatementDefinition <$> template) + <*> apopt checkBoxField (fslI MsgSchoolSheetExamAuthorshipStatementAllowOther) (sfSheetExamAuthorshipStatementAllowOther <$> template <|> pure True) where ldapOrgs :: HandlerFor UniWorX (OptionList (CI Text)) ldapOrgs = fmap (mkOptionList . map (\t -> Option (CI.original t) t (CI.original t)) . Set.toAscList) . runDB $ @@ -99,6 +103,15 @@ schoolToForm :: SchoolId -> DB (Form SchoolForm) schoolToForm ssh = do School{..} <- get404 ssh ldapFrags <- selectList [SchoolLdapSchool ==. Just ssh] [] + + -- TODO: allow for separate translations + -- let getAuthorshipStatementDefs = maybe (return Nothing) (\definitionId -> Just <$> selectList [ AuthorshipStatementDefinitionTranslationDefinition ==. definitionId ] []) + -- authorshipStatementDefs <- getAuthorshipStatementDefs schoolSheetAuthorshipStatementDefinition + -- examAuthorshipStatementDefs <- getAuthorshipStatementDefs schoolSheetExamAuthorshipStatementDefinition + + mSheetAuthorshipStatementDefinition <- maybe (return Nothing) get schoolSheetAuthorshipStatementDefinition + mSheetExamAuthorshipStatementDefinition <- maybe (return Nothing) get schoolSheetExamAuthorshipStatementDefinition + return . mkSchoolForm (Just ssh) $ Just SchoolForm { sfShorthand = schoolShorthand , sfName = schoolName @@ -109,9 +122,11 @@ schoolToForm ssh = do , sfExamDiscouragedModes = schoolExamDiscouragedModes , sfExamCloseMode = schoolExamCloseMode , sfSheetAuthorshipStatementMode = schoolSheetAuthorshipStatementMode - , sfSheetAuthorshipStatementExamMode = schoolSheetAuthorshipStatementExamMode - , sfSheetAuthorshipStatementText = schoolSheetAuthorshipStatementText + , sfSheetAuthorshipStatementDefinition = authorshipStatementDefinitionContent <$> mSheetAuthorshipStatementDefinition , sfSheetAuthorshipStatementAllowOther = schoolSheetAuthorshipStatementAllowOther + , sfSheetExamAuthorshipStatementMode = schoolSheetExamAuthorshipStatementMode + , sfSheetExamAuthorshipStatementDefinition = authorshipStatementDefinitionContent <$> mSheetExamAuthorshipStatementDefinition + , sfSheetExamAuthorshipStatementAllowOther = schoolSheetExamAuthorshipStatementAllowOther } @@ -126,6 +141,9 @@ postSchoolEditR ssh = do formResult sfResult $ \SchoolForm{..} -> do runDB $ do + let + mAuthorshipStatementId = error "WIP upsert authorship statement" + mExamAuthorshipStatementId = error "WIP upsert exam authorship statement" update ssh [ SchoolName =. sfName , SchoolExamMinimumRegisterBeforeStart =. sfExamMinimumRegisterBeforeStart @@ -134,9 +152,11 @@ postSchoolEditR ssh = do , SchoolExamDiscouragedModes =. sfExamDiscouragedModes , SchoolExamCloseMode =. sfExamCloseMode , SchoolSheetAuthorshipStatementMode =. sfSheetAuthorshipStatementMode - , SchoolSheetAuthorshipStatementExamMode =. sfSheetAuthorshipStatementExamMode - , SchoolSheetAuthorshipStatementText =. sfSheetAuthorshipStatementText + , SchoolSheetAuthorshipStatementDefinition =. mAuthorshipStatementId , SchoolSheetAuthorshipStatementAllowOther =. sfSheetAuthorshipStatementAllowOther + , SchoolSheetExamAuthorshipStatementMode =. sfSheetExamAuthorshipStatementMode + , SchoolSheetExamAuthorshipStatementDefinition =. mExamAuthorshipStatementId + , SchoolSheetExamAuthorshipStatementAllowOther =. sfSheetExamAuthorshipStatementAllowOther ] forM_ sfOrgUnits $ \schoolLdapOrgUnit -> void $ upsert SchoolLdap @@ -171,6 +191,9 @@ postSchoolNewR = do formResult sfResult $ \SchoolForm{..} -> do let ssh = SchoolKey sfShorthand insertOkay <- runDB $ do + let + mAuthorshipStatementId = error "WIP insert authorship statement" + mExamAuthorshipStatementId = error "WIP insert exam authorship statement" didInsert <- is _Just <$> insertUnique School { schoolShorthand = sfShorthand , schoolName = sfName @@ -180,9 +203,11 @@ postSchoolNewR = do , schoolExamDiscouragedModes = sfExamDiscouragedModes , schoolExamCloseMode = sfExamCloseMode , schoolSheetAuthorshipStatementMode = sfSheetAuthorshipStatementMode - , schoolSheetAuthorshipStatementExamMode = sfSheetAuthorshipStatementExamMode - , schoolSheetAuthorshipStatementText = sfSheetAuthorshipStatementText + , schoolSheetAuthorshipStatementDefinition = mAuthorshipStatementId , schoolSheetAuthorshipStatementAllowOther = sfSheetAuthorshipStatementAllowOther + , schoolSheetExamAuthorshipStatementMode = sfSheetExamAuthorshipStatementMode + , schoolSheetExamAuthorshipStatementDefinition = mExamAuthorshipStatementId + , schoolSheetExamAuthorshipStatementAllowOther = sfSheetExamAuthorshipStatementAllowOther } when didInsert $ do insert_ UserFunction diff --git a/src/Model/Migration/Definitions.hs b/src/Model/Migration/Definitions.hs index 537127fb5..78ac1db9e 100644 --- a/src/Model/Migration/Definitions.hs +++ b/src/Model/Migration/Definitions.hs @@ -103,6 +103,9 @@ data ManualMigration | Migration20210208StudyFeaturesRelevanceCachedUUIDs | Migration20210318CrontabSubmissionRatedNotification | Migration20210608SeparateTermActive + -- TODO: migration regarding authorship statements + -- - apply desired non-default modes for IfI + -- - set authorship statement texts for IfI deriving (Eq, Ord, Read, Show, Enum, Bounded, Generic, Typeable) deriving anyclass (Universe, Finite) diff --git a/test/Database/Fill.hs b/test/Database/Fill.hs index fe3480ff7..f510ab53c 100644 --- a/test/Database/Fill.hs +++ b/test/Database/Fill.hs @@ -411,8 +411,9 @@ fillDb = do , termLectureEnd } void . insert_ $ TermActive (TermKey term) (toMidnight $ addDays (-60) termStart) (Just . beforeMidnight $ addDays 60 termEnd) Nothing - ifi <- insert' $ School "Institut für Informatik" "IfI" (Just $ 14 * nominalDay) (Just $ 10 * nominalDay) True (ExamModeDNF predDNFFalse) (ExamCloseOnFinished True) SchoolAuthorshipStatementModeOptional SchoolAuthorshipStatementModeRequired (Just "Erklärung über die eigenständige Bearbeitung

Hiermit erkläre ich, dass ich die vorliegende Abgabe vollständig selbstständig angefertigt habe, bzw. dass bei einer Gruppen-Abgabe nur die bei der Abgabe benannten Personen mitgewirkt haben.

Quellen und Hilfsmittel über den Rahmen der Lehrveranstaltung hinaus sind als solche markiert und angegeben. Direkte Zitate sind als solche kenntlich gemacht.

Ich bin mir darüber im Klaren, dass Verstöße durch Plagiate oder Zusammenarbeit mit Dritten zum Ausschluss von der Veranstaltung führen.") False - mi <- insert' $ School "Institut für Mathematik" "MI" Nothing Nothing False (ExamModeDNF predDNFFalse) (ExamCloseOnFinished False) SchoolAuthorshipStatementModeNone SchoolAuthorshipStatementModeOptional Nothing True + ifiAuthorshipStatement <- insert $ AuthorshipStatementDefinition "Erklärung über die eigenständige Bearbeitung

Hiermit erkläre ich, dass ich die vorliegende Abgabe vollständig selbstständig angefertigt habe, bzw. dass bei einer Gruppen-Abgabe nur die bei der Abgabe benannten Personen mitgewirkt haben. Quellen und Hilfsmittel über den Rahmen der Lehrveranstaltung hinaus sind als solche markiert und angegeben. Direkte Zitate sind als solche kenntlich gemacht. Ich bin mir darüber im Klaren, dass Verstöße durch Plagiate oder Zusammenarbeit mit Dritten zum Ausschluss von der Veranstaltung führen.

Statement of Authorship

TODO English version

" + ifi <- insert' $ School "Institut für Informatik" "IfI" (Just $ 14 * nominalDay) (Just $ 10 * nominalDay) True (ExamModeDNF predDNFFalse) (ExamCloseOnFinished True) SchoolAuthorshipStatementModeOptional (Just ifiAuthorshipStatement) True SchoolAuthorshipStatementModeRequired (Just ifiAuthorshipStatement) False + mi <- insert' $ School "Institut für Mathematik" "MI" Nothing Nothing False (ExamModeDNF predDNFFalse) (ExamCloseOnFinished False) SchoolAuthorshipStatementModeNone Nothing True SchoolAuthorshipStatementModeOptional Nothing True void . insert' $ UserFunction gkleen ifi SchoolAdmin void . insert' $ UserFunction gkleen mi SchoolAdmin void . insert' $ UserFunction fhamann ifi SchoolAdmin