fix(workflows): cleanup

This commit is contained in:
Gregor Kleen 2020-11-25 15:00:16 +01:00
parent 82b3a6364c
commit 0a3eaa2994
13 changed files with 1605 additions and 661 deletions

View File

@ -537,6 +537,17 @@ UnauthorizedPasswordResetToken: This authorisation-token may no longer be used t
UnauthorizedAllocatedCourseRegister: Direct enrollment to this course is currently not allowed due to participation in a central allocation
UnauthorizedAllocatedCourseDeregister: Deregistration from this course is currently not allowed due to participation in a central allocation
UnauthorizedAllocatedCourseDelete: Courses that participate in a central allocation may not be deleted
UnauthorizedWorkflowInitiate: You currently may not initiate a new running workflow
UnauthorizedWorkflowWrite: You are currently not allowed to initiate any state transition within the workflow
UnauthorizedWorkflowRead: The workflow currently contains no states or data you are permitted to view
UnauthorizedWorkflowInstancesNotEmpty: There are workflow instances for which you are allowed to initiate a new running workflow
UnauthorizedWorkflowWorkflowsNotEmpty: There are running workflows, which you may view
UnauthorizedWorkflowFiles: You are not allowed to download the given workflow files in the given historical state
WorkflowRoleUserMismatch: You aren't any of the users authorized by the workflow
WorkflowRoleAlreadyInitiated: This workflow was already initiated
WorkflowRoleNoSuchWorkflowWorkflow: The given workflow could not be found
WorkflowRoleNoPayload: This workflow does not contain any data
EMail: Email
EMailUnknown email: Email #{email} does not belong to any known user.
@ -1410,6 +1421,20 @@ MenuAdminCrontab: Crontab
MenuAdminWorkflowDefinitionList: Workflows
MenuAdminWorkflowDefinitionNew: New workflow definition
MenuAdminWorkflowDefinitionDelete: Delete
MenuAdminWorkflowInstanceList: Workflow instances
MenuAdminWorkflowInstanceNew: New workflow instance
MenuAdminWorkflowDefinitionInstantiate: Instantiate
MenuWorkflowInstanceDelete: Delete
MenuWorkflowInstanceWorkflows: Running workflows
MenuWorkflowInstanceInitiate: Start workflow
MenuWorkflowInstanceEdit: Edit
MenuWorkflowWorkflowList: Running workflows
MenuWorkflowWorkflowEdit: Edit
MenuWorkflowWorkflowDelete: Delete
MenuGlobalWorkflowInstanceList: System-wide workflows
MenuTopWorkflowInstanceList: Workflows
MenuTopWorkflowWorkflowList: Running workflows
MenuTopWorkflowWorkflowListHeader: Workflows
BreadcrumbSubmissionFile: File
BreadcrumbSubmissionUserInvite: Invitation to participate in a submission
@ -1491,6 +1516,25 @@ BreadcrumbAdminWorkflowDefinitionList: Workflow definitions
BreadcrumbAdminWorkflowDefinitionNew: New workflow definition
BreadcrumbAdminWorkflowDefinitionEdit renderedWorkflowScope' wfdn: #{wfdn} (#{renderedWorkflowScope'})
BreadcrumbAdminWorkflowDefinitionDelete: Delete
BreadcrumbAdminWorkflowDefinitionInstantiate: Instantiate
BreadcrumbAdminWorkflowInstanceList: Workflow instances
BreadcrumbAdminWorkflowInstanceNew: New workflow-instance
BreadcrumbAdminWorkflowWorkflowList: Initiated workflows
BreadcrumbAdminWorkflowWorkflowNew: Initiate workflow
BreadcrumbWorkflowInstanceEdit win: #{win}
BreadcrumbWorkflowInstanceDelete: Delete
BreadcrumbWorkflowInstanceWorkflowList: Running workflows
BreadcrumbWorkflowInstanceInitiate: Start workflow
BreadcrumbWorkflowInstanceList: Workflows
BreadcrumbWorkflowInstanceNew: New workflow
BreadcrumbWorkflowWorkflowList: Running workflows
BreadcrumbWorkflowWorkflow workflow: #{toPathPiece workflow}
BreadcrumbWorkflowWorkflowFiles: Files
BreadcrumbWorkflowWorkflowEdit: Edit
BreadcrumbWorkflowWorkflowDelete: Delete
BreadcrumbGlobalWorkflowInstanceList: System-wide workflows
BreadcrumbTopWorkflowInstanceList: Workflows
BreadcrumbTopWorkflowWorkflowList: Running workflows
ExternalExamEdit coursen examn: Edit: #{coursen}, #{examn}
ExternalExamGrades coursen examn: Exam achievements: #{coursen}, #{examn}
@ -1546,6 +1590,7 @@ AuthTagAuthentication: User is authenticated
AuthTagRead: Access is read only
AuthTagWrite: Access might write
AuthTagSubmissionGroup: User is part of a submission group
AuthTagWorkflow: User has matching workflow role
DeleteCopyStringIfSure n: If you are sure that you want to permanently delete the #{pluralEN n "object" "objects"} listed below, please copy the shown text.
DeletePressButtonIfSure n: If you are sure that you want to permanently delete the #{pluralEN n "object" "objects"} listed below, please confirm the action by pressing the button.
@ -2942,15 +2987,78 @@ WorkflowScopeKindTerm: Per term
WorkflowScopeKindSchool: Per school
WorkflowScopeKindTermSchool: Per school & term
WorkflowScopeKindCourse: Per course
WorkflowScopeGlobal: System-wide
WorkflowScopeTermSchool tid ssh: #{tid} #{ssh}
WorkflowScopeCourse tid ssh csh: #{tid} #{ssh} #{csh}
WorkflowDefinitionScope: Scope
WorkflowDefinitionName: Name
WorkflowDefinitionDescriptions: Description
WorkflowDefinitionDescriptionsLanguageExists: A description in this language already exists
WorkflowDescriptionLanguage: Language code (RFC1766)
WorkflowDescriptionTitle: Title
WorkflowDescription: Description
GlobalWorkflowInstancesHeading: Workflows (system-wide)
GlobalWorkflowInstancesTitle: Workflows (system-wide)
GlobalWorkflowInstanceInitiateHeading workflowInstanceTitle: Initiate workflow: #{workflowInstanceTitle}
GlobalWorkflowInstanceInitiateTitle: Initiate workflow
SchoolWorkflowInstancesHeading ssh: Workflows (#{ssh})
SchoolWorkflowInstancesTitle ssh: Workflows (#{ssh})
SchoolWorkflowInstanceInitiateHeading ssh workflowInstanceTitle: Initiate workflow: #{ssh}, #{workflowInstanceTitle}
SchoolWorkflowInstanceInitiateTitle ssh: Initiate workflow: #{ssh}
WorkflowEdgeNumberedVariant edgeLabel i: #{edgeLabel} (variant #{i})
WorkflowEdgeFormEdge: Action
WorkflowEdgeFormHiddenPayload i: Hidden dataset #{i}
WorkflowEdgeFormPayloadOneFieldRequired: At least one field per dataset needs to be filled
WorkflowEdgeFormPayloadOneFieldRequiredFor payloadDisplayLabel: At least one field for “#{payloadDisplayLabel}” needs to be filled
WorkflowEdgeFormFieldNumberTooSmall minSci: Number must be at least #{formatScientific Scientific.Generic Nothing minSci}
WorkflowEdgeFormFieldNumberTooLarge maxSci: Number must be at most #{formatScientific Scientific.Generic Nothing maxSci}
WorkflowEdgeFormFieldUserNotFound: Email could not be resolved to an user
WorkflowEdgeFormFieldMultipleNoneAdded: No entries (yet)
WorkflowEdgeFormFieldCaptureUserLabel: Current user
WorkflowWorkflowWorkflowHistoryHeading: History
WorkflowWorkflowWorkflowEdgeFormHeading: Trigger action within workflow
WorkflowWorkflowWorkflowEdgeSuccess: Successfully triggered action
WorkflowWorkflowWorkflowHistoryUserSelf: You
WorkflowWorkflowWorkflowHistoryUserNotLoggedIn: Not-logged in user
WorkflowWorkflowWorkflowHistoryUserGone: Deleted user
WorkflowWorkflowWorkflowHistoryUserHidden: Hidden user
WorkflowWorkflowWorkflowHistoryUserAutomatic: Automatic
WorkflowWorkflowWorkflowHistoryActionAutomatic: Automatic
WorkflowWorkflowWorkflowHistoryStateHidden: Hidden state
WorkflowWorkflowWorkflowHistoryActionLabel: Action
WorkflowWorkflowWorkflowHistoryFromLabel: Previous state
WorkflowWorkflowWorkflowHistoryToLabel: New state
WorkflowWorkflowWorkflowHistoryPayloadLabel: Data changes
WorkflowWorkflowFilesArchiveName wwCID wpl stCID: #{foldCase (toPathPiece wwCID)}-#{foldCase (toPathPiece stCID)}-#{foldCase (foldMap unidecode (toPathPiece wpl))}.zip
WorkflowWorkflowWorkflowStateHeading: State/Data
WorkflowWorkflowWorkflowPayloadHeading: Current data
WorkflowWorkflowWorkflowStateStateLabel: Current state
WorkflowWorkflowWorkflowStateStateHidden: Hidden state
WorkflowPayloadFiles: File(s)
WorkflowPayloadBoolTrue: Yes
WorkflowPayloadBoolFalse: No
WorkflowPayloadUserGone: Deleted user
TopWorkflowInstancesHeading: Workflows
TopWorkflowInstancesTitle: Workflows
GlobalWorkflowWorkflowWorkflowHeading workflowWorkflowId: Workflow #{toPathPiece workflowWorkflowId}
GlobalWorkflowWorkflowWorkflowTitle workflowWorkflowId: Workflow #{toPathPiece workflowWorkflowId}
SchoolWorkflowWorkflowWorkflowHeading ssh workflowWorkflowId: Workflow #{ssh}, #{toPathPiece workflowWorkflowId}
SchoolWorkflowWorkflowWorkflowTitle ssh workflowWorkflowId: Workflow #{ssh}, #{toPathPiece workflowWorkflowId}
WorkflowDefinitionGraph: Specification
WorkflowDefinitionKeyDoesNotExist renderedCryptoID: Referenced id does not exist: #{renderedCryptoID}
WorkflowDefinitionFiles: Files
WorkflowFileIdentDoesNotExist fileIdent: Referenced file does not exist: #{fileIdent}
WorkflowUserDoesNotExist userIdent: Referenced user does not exist: #{userIdent}
WorkflowDefinitionFileIdentExists: A file with the given reference id already exists
WorkflowDefinitionFileIdent: File reference id
WorkflowDefinitionFile: File
@ -2959,6 +3067,9 @@ WorkflowDefinitionEdited: Successfully replaced workflow definition
WorkflowDefinitionCollision: A workflow definition with this name already exists
WorkflowDefinitionNewTitle: Create new workflow definition
WorkflowDefinitionEditTitle: Edit workflow definition
WorkflowDefinitionInstanceCategory: Category
WorkflowDefinitionWarningLinterIssuesMessage: There were linter issues
WorkflowDefinitionWarningLinterIssues: There are the following linter issues:
WorkflowDefinitionListTitle: Workflow definitions
WorkflowDefinitionInstanceCount: Instances
@ -2967,6 +3078,22 @@ WorkflowDefinitionConcreteInstanceCount num: #{num} instances
WorkflowDefinitionConcreteWorkflowCount num: #{num} workflows
WorkflowDefinitionDeleteQuestion: Do you really want to delete the workflow definition listed below?
WorkflowDefinitionDeleted: Successfully deleted workflow definition
WorkflowDefinitionInstantiateTitle: Instantiate workflow definition
WorkflowDefinitionInstantiated: Instance created
WorkflowScope: Scope
WorkflowInstanceName: Name
WorkflowInstanceCategory: Category
WorkflowInstanceCollision: There already exists a workflow instance with the given name and category
WorkflowInstanceListTitle: Workflow instances
WorkflowInstanceDescription: Instance description
WorkflowInstanceDescriptions: Instance description
WorkflowInstanceDescriptionsLanguageExists: A instance description in the given language already exists
WorkflowInstanceCreated: Instance created
WorkflowInstanceDescriptionTitle: Instance title
WorkflowInstanceWorkflowCount: Workflows
WorkflowInstanceInitiateSuccess: Successfully initiated workflow
ChangelogItemFeature: Feature
ChangelogItemBugfix: Bugfix

View File

@ -54,6 +54,9 @@ import qualified Text.Blaze as Blaze
import qualified Text.Blaze.Renderer.Text as Blaze
{-# ANN module ("HLint: ignore Use newtype instead of data"::String) #-}
data WorkflowEdgeForm = WorkflowEdgeForm
{ wefEdge :: (WorkflowGraphNodeLabel, WorkflowGraphEdgeLabel)
, wefPayload :: Map WorkflowPayloadLabel (Set (WorkflowFieldPayloadW FileReference UserId))
@ -256,7 +259,7 @@ workflowEdgePayloadFields specs = evalRWST (forM specs $ runExceptT . renderSpec
-> Field Handler payload'
-> FieldSettings UniWorX
-> Maybe payload'
-> _ ((Bool, FormResult (Maybe (NonEmpty (WorkflowFieldPayloadW FileReference UserId)))))
-> _ (Bool, FormResult (Maybe (NonEmpty (WorkflowFieldPayloadW FileReference UserId))))
f' toNonEmpty' isOpt fld fs mx = lift . (<* tell (All isOpt)) . lift $ over (_2 . mapped) (fmap (fmap . review $ _WorkflowFieldPayloadW . _WorkflowFieldPayload) . toNonEmpty' =<<) . bool (is (_FormSuccess . _Just) &&& id) (True, ) isOpt <$> wopt fld fs (Just <$> mx)
f :: forall payload'.
_
@ -264,7 +267,7 @@ workflowEdgePayloadFields specs = evalRWST (forM specs $ runExceptT . renderSpec
-> Field Handler payload'
-> FieldSettings UniWorX
-> Maybe payload'
-> _ ((Bool, FormResult (Maybe (NonEmpty (WorkflowFieldPayloadW FileReference UserId)))))
-> _ (Bool, FormResult (Maybe (NonEmpty (WorkflowFieldPayloadW FileReference UserId))))
f = f' (nonEmpty . pure)
extractPrevs :: forall payload' m xs.
( IsWorkflowFieldPayload' FileReference UserId payload'
@ -314,9 +317,9 @@ workflowEdgePayloadFields specs = evalRWST (forM specs $ runExceptT . renderSpec
)
( fsl (slI18n wpfnLabel)
& maybe id (addPlaceholder . slI18n) wpfnPlaceholder
& maybe id (\wpfnMin' -> addAttr "min" . tshow $ formatScientific Scientific.Fixed Nothing wpfnMin') wpfnMin
& maybe id (\wpfnMax' -> addAttr "max" . tshow $ formatScientific Scientific.Fixed Nothing wpfnMax') wpfnMax
& maybe (addAttr "step" "any") (\wpfnStep' -> addAttr "step" . tshow $ formatScientific Scientific.Fixed Nothing wpfnStep') wpfnStep
& maybe id (addAttr "min" . tshow . formatScientific Scientific.Fixed Nothing) wpfnMin
& maybe id (addAttr "max" . tshow . formatScientific Scientific.Fixed Nothing) wpfnMax
& maybe (addAttr "step" "any") (addAttr "step" . tshow . formatScientific Scientific.Fixed Nothing) wpfnStep
& maybe id (addName . ($ "number")) mNudge
)
(prev <|> wpfnDefault)
@ -423,11 +426,11 @@ workflowEdgePayloadFields specs = evalRWST (forM specs $ runExceptT . renderSpec
-> (Text -> Text)
-> FieldView UniWorX
-> Maybe (Html -> MForm (ExceptT WorkflowPayloadLabel Handler) (FormResult (Map ListPosition (Maybe (WorkflowFieldPayloadW FileReference UserId)) -> FormResult (Map ListPosition (Maybe (WorkflowFieldPayloadW FileReference UserId)))), Widget))
miAdd _pos _dim nudge submitView = Just $ \csrf -> over (_1 . _FormSuccess) tweakRes <$> miForm nudge (Left submitView) csrf
miAdd _pos _dim nudge submitView = Just $ over (mapped . _1 . _FormSuccess) tweakRes . miForm nudge (Left submitView)
where tweakRes :: Maybe (NonEmpty (WorkflowFieldPayloadW FileReference UserId))
-> Map ListPosition (Maybe (WorkflowFieldPayloadW FileReference UserId))
-> FormResult (Map ListPosition (Maybe (WorkflowFieldPayloadW FileReference UserId)))
tweakRes newDat prevData = Map.fromList . zip [startKey..] <$> pure (map Just $ newDat ^.. _Just . folded)
tweakRes newDat prevData = pure . Map.fromList . zip [startKey..] . map Just $ newDat ^.. _Just . folded
where startKey = maybe 0 succ $ fst <$> Map.lookupMax prevData
miCell :: ListPosition

View File

@ -113,7 +113,7 @@ workflowGraphForm template = validateAForm validateWorkflowGraphForm . hoistAFor
fileForm :: (Text -> Text) -> Maybe (FileIdent, FileReference) -> Form (FileIdent, FileReference)
fileForm nudge fileTemplate csrf = do
(fileIdentRes, fileIdentView) <- mpreq (isoField _Unwrapped ciField) (fslI MsgWorkflowDefinitionFileIdent & addName (nudge "ident")) (view _1 <$> fileTemplate)
(fileRes, fileView) <- mpreq (singleFileField . fromMaybe (return ()) $ views _2 yield <$> fileTemplate) (fslI MsgWorkflowDefinitionFile & addName (nudge "file")) (views _2 yield <$> fileTemplate)
(fileRes, fileView) <- mpreq (singleFileField $ maybe (return ()) (views _2 yield) fileTemplate) (fslI MsgWorkflowDefinitionFile & addName (nudge "file")) (views _2 yield <$> fileTemplate)
fileRes' <- liftHandler . runDB $ case fileRes of
FormSuccess uploads -> maybe FormMissing FormSuccess <$> runConduit (transPipe liftHandler uploads .| C.head)
FormFailure errs -> return $ FormFailure errs
@ -155,8 +155,8 @@ toWorkflowGraphForm g = liftHandler . fmap (uncurry WorkflowGraphForm . over _2
Just fIdent -> return fIdent
Nothing -> do
cMap <- State.get
let candidateIdents = map (review _Wrapped . CI.mk) $
map pack $ fileReferenceTitle : [ base <.> show n <.> ext | n <- [1..] :: [Natural], let (base, ext) = splitExtension fileReferenceTitle ]
let candidateIdents = map (review _Wrapped . CI.mk . pack) $
fileReferenceTitle : [ base <.> show n <.> ext | let (base, ext) = splitExtension fileReferenceTitle, n <- [1..] :: [Natural] ]
fIdent = case filter (`Bimap.notMember` cMap) candidateIdents of
fIdent' : _ -> fIdent'
[] -> error "candidateIdents should be infinite; cMap should be finite"

View File

@ -116,7 +116,7 @@ workflowR wwId = do
mAuthId <- maybeAuthId
guardM . lift . lift . hoist liftHandler $ mayViewWorkflowAction mAuthId wwId act
stCID <- encrypt stIx
stCID <- encryptWorkflowStateIndex wwId stIx
let nodeView nodeLbl = do
WorkflowNodeView{..} <- hoistMaybe $ Map.lookup nodeLbl wgNodes >>= wgnViewers
guardM $ anyM (otoList wnvViewers) hasWorkflowRole'
@ -182,7 +182,7 @@ workflowR wwId = do
<> (compareUnicode `on` userDisplayName) uA uB
<> comparing userIdent uA uB
(WFPUser{}, _ ) -> GT
flip mapM payload' $ \(lblText, (otoList -> payloads, fRoute)) -> fmap ((lblText, ) . over _1 (sortBy payloadSort) . over _2 (bool Nothing (Just fRoute). getAny)) . execWriterT . flip mapM_ payloads $ \case
forM payload' $ \(lblText, (otoList -> payloads, fRoute)) -> fmap ((lblText, ) . over _1 (sortBy payloadSort) . over _2 (bool Nothing (Just fRoute). getAny)) . execWriterT . forM_ payloads $ \case
WorkflowFieldPayloadW (WFPText t ) -> tell . (, mempty) . pure $ WorkflowFieldPayloadW (WFPText t)
WorkflowFieldPayloadW (WFPNumber n ) -> tell . (, mempty) . pure $ WorkflowFieldPayloadW (WFPNumber n)
WorkflowFieldPayloadW (WFPBool b ) -> tell . (, mempty) . pure $ WorkflowFieldPayloadW (WFPBool b)
@ -262,7 +262,7 @@ getWorkflowFilesR :: WorkflowWorkflowId -> WorkflowPayloadLabel -> CryptoUUIDWor
getWorkflowFilesR wwId wpl stCID = do
fRefs <- runDB $ do
WorkflowWorkflow{..} <- get404 wwId
stIx <- decrypt stCID
stIx <- decryptWorkflowStateIndex wwId stCID
payloads <- maybeT notFound . workflowStateSection stIx $ _DBWorkflowState # workflowWorkflowState
mAuthId <- maybeAuthId
payloads' <- fmap (Map.findWithDefault Set.empty wpl . workflowStateCurrentPayloads) . filterM (mayViewWorkflowAction mAuthId wwId) $ otoList payloads

View File

@ -247,7 +247,7 @@ class FileReferenceTitleMapConvertible add f1 f2 where
_FileReferenceTitleMap :: Traversal (FileReferenceTitleMap f1 add) (FileReferenceTitleMap f2 add) (f1, add) (f2, add)
instance FileReferenceTitleMapConvertible add FileReference FileReference where
_FileReferenceTitleMap = iso unFileReferenceFileReferenceTitleMap FileReferenceFileReferenceTitleMap . iso (map (\(fileReferenceTitle, (FileReferenceFileReferenceTitleMapElem fileReferenceContent fileReferenceModified additional)) -> (FileReference{..}, additional)) . Map.toList) (Map.fromList . map (\(FileReference{..}, additional) -> (fileReferenceTitle, FileReferenceFileReferenceTitleMapElem fileReferenceContent fileReferenceModified additional))) . traverse
_FileReferenceTitleMap = iso unFileReferenceFileReferenceTitleMap FileReferenceFileReferenceTitleMap . iso (map (\(fileReferenceTitle, FileReferenceFileReferenceTitleMapElem fileReferenceContent fileReferenceModified additional) -> (FileReference{..}, additional)) . Map.toList) (Map.fromList . map (\(FileReference{..}, additional) -> (fileReferenceTitle, FileReferenceFileReferenceTitleMapElem fileReferenceContent fileReferenceModified additional))) . traverse
data FileFieldUserOption a = FileFieldUserOption

View File

@ -68,10 +68,7 @@ predNFAesonOptions = defaultOptions
}
workflowGraphAesonOptions, workflowGraphEdgeAesonOptions, workflowGraphNodeAesonOptions, workflowActionAesonOptions, workflowPayloadViewAesonOptions, workflowNodeViewAesonOptions, workflowNodeMessageAesonOptions :: Options
workflowGraphAesonOptions = defaultOptions
{ fieldLabelModifier = camelToPathPiece' 1
}
workflowGraphEdgeAesonOptions, workflowGraphNodeAesonOptions, workflowActionAesonOptions, workflowPayloadViewAesonOptions, workflowNodeViewAesonOptions, workflowNodeMessageAesonOptions :: Options
workflowGraphEdgeAesonOptions = defaultOptions
{ constructorTagModifier = camelToPathPiece' 3
, fieldLabelModifier = camelToPathPiece' 1

View File

@ -61,7 +61,7 @@ import Utils.Lens.TH
----- WORKFLOW GRAPH -----
data WorkflowGraph fileid userid = WorkflowGraph
newtype WorkflowGraph fileid userid = WorkflowGraph
{ wgNodes :: Map WorkflowGraphNodeLabel (WorkflowGraphNode fileid userid)
}
deriving (Generic, Typeable)
@ -342,7 +342,7 @@ workflowStateSection :: MonadPlus m
=> WorkflowStateIndex
-> WorkflowState fileid userid
-> m (WorkflowState fileid userid)
workflowStateSection i wSt = maybe mzero return . fromNullable . Seq.fromList =<< sequenceA (map (flip workflowStateIndex wSt) [0..i])
workflowStateSection i wSt = maybe mzero return . fromNullable . Seq.fromList =<< traverse (`workflowStateIndex` wSt) [0..i]
data WorkflowAction fileid userid = WorkflowAction
{ wpTo :: WorkflowGraphNodeLabel
@ -628,14 +628,14 @@ instance (FromJSON userid, Ord userid) => FromJSON (WorkflowPayloadView userid)
parseJSON = genericParseJSON workflowPayloadViewAesonOptions
instance (ToJSON fileid, ToJSON userid, ToJSON (FileField fileid)) => ToJSON (WorkflowGraph fileid userid) where
toJSON = genericToJSON workflowGraphAesonOptions
toJSON = toJSON . wgNodes
instance ( FromJSON fileid, FromJSON userid
, Ord fileid, Ord userid
, Typeable fileid, Typeable userid
, FromJSON (FileField fileid)
, Ord (FileField fileid)
) => FromJSON (WorkflowGraph fileid userid) where
parseJSON = genericParseJSON workflowGraphAesonOptions
parseJSON = fmap WorkflowGraph . parseJSON
instance (ToJSON fileid, ToJSON userid, ToJSON (FileField fileid)) => ToJSON (WorkflowGraphEdge fileid userid) where
toJSON = genericToJSON workflowGraphEdgeAesonOptions
@ -652,11 +652,10 @@ instance ToJSON WorkflowGraphEdgeFormOrder where
Nothing -> JSON.String "_"
Just sci -> JSON.Number sci
instance FromJSON WorkflowGraphEdgeFormOrder where
parseJSON v = fmap WorkflowGraphEdgeFormOrder $ asum
[ Just <$> parseJSON v
, flip (JSON.withText "WorkflowGraphEdgeFormOrder") v $ \t -> maybe (fail "WorkflowGraphEdgeFormOrder: could not parse String as Number") (return . Just) $ readMay t
, flip (JSON.withText "WorkflowGraphEdgeFormOrder") v $ bool (fail "WorkflowGraphEdgeFormOrder: unexpected String, expecting either number or \"_\"") (pure Nothing) . (== "_")
]
parseJSON v = fmap WorkflowGraphEdgeFormOrder $
Just <$> parseJSON v
<|> JSON.withText "WorkflowGraphEdgeFormOrder" (maybe (fail "WorkflowGraphEdgeFormOrder: could not parse String as Number") (return . Just) . readMay) v
<|> JSON.withText "WorkflowGraphEdgeFormOrder" (bool (fail "WorkflowGraphEdgeFormOrder: unexpected String, expecting either number or \"_\"") (pure Nothing) . (== "_")) v
instance ToJSONKey WorkflowGraphEdgeFormOrder where
toJSONKey = JSON.ToJSONKeyText (maybe "_" toText' . unWorkflowGraphEdgeFormOrder) (maybe (JSON.text "_") toEncoding' . unWorkflowGraphEdgeFormOrder)
@ -678,17 +677,16 @@ instance ( FromJSON fileid, FromJSON userid
, FromJSON (FileField fileid), Ord (FileField fileid)
) => FromJSON (WorkflowGraphEdgeForm fileid userid) where
parseJSON = JSON.withObject "WorkflowGraphEdgeForm" $ \o -> do
o' <- parseJSON $ JSON.Object o :: JSON.Parser (Map WorkflowPayloadLabel (NonNull (Set (JSON.Value))))
fmap WorkflowGraphEdgeForm . for o' $ \(Set.toList . toNullable -> o'') -> fmap (impureNonNull . Set.fromList) . for o'' $ \o''' -> asum
[ parseJSON o'''
, impureNonNull . Map.singleton (WorkflowGraphEdgeFormOrder Nothing) <$> parseJSON o'''
]
o' <- parseJSON $ JSON.Object o :: JSON.Parser (Map WorkflowPayloadLabel (NonNull (Set JSON.Value)))
fmap WorkflowGraphEdgeForm . for o' $ \(Set.toList . toNullable -> o'') -> fmap (impureNonNull . Set.fromList) . for o'' $ \o''' ->
parseJSON o'''
<|> impureNonNull . Map.singleton (WorkflowGraphEdgeFormOrder Nothing) <$> parseJSON o'''
instance (ToJSON fileid, ToJSON userid, ToJSON (FileField fileid)) => ToJSON (WorkflowPayloadSpec fileid userid) where
toJSON (WorkflowPayloadSpec f) = toJSON f
instance (ToJSON fileid, ToJSON userid, ToJSON (FileField fileid)) => ToJSON (WorkflowPayloadField fileid userid payload) where
toJSON (WorkflowPayloadFieldText{..}) = JSON.object $ omitNothing
toJSON WorkflowPayloadFieldText{..} = JSON.object $ omitNothing
[ "tag" JSON..= WPFText'
, "label" JSON..= wpftLabel
, "placeholder" JSON..= wpftPlaceholder
@ -697,7 +695,7 @@ instance (ToJSON fileid, ToJSON userid, ToJSON (FileField fileid)) => ToJSON (Wo
, "large" JSON..= wpftLarge
, "optional" JSON..= wpftOptional
]
toJSON (WorkflowPayloadFieldNumber{..}) = JSON.object $ omitNothing
toJSON WorkflowPayloadFieldNumber{..} = JSON.object $ omitNothing
[ "tag" JSON..= WPFNumber'
, "label" JSON..= wpfnLabel
, "placeholder" JSON..= wpfnPlaceholder
@ -708,42 +706,42 @@ instance (ToJSON fileid, ToJSON userid, ToJSON (FileField fileid)) => ToJSON (Wo
, "step" JSON..= wpfnStep
, "optional" JSON..= wpfnOptional
]
toJSON (WorkflowPayloadFieldBool{..}) = JSON.object $ omitNothing
toJSON WorkflowPayloadFieldBool{..} = JSON.object $ omitNothing
[ "tag" JSON..= WPFBool'
, "label" JSON..= wpfbLabel
, "tooltip" JSON..= wpfbTooltip
, "default" JSON..= wpfbDefault
, "optional" JSON..= wpfbOptional
]
toJSON (WorkflowPayloadFieldDay{..}) = JSON.object $ omitNothing
toJSON WorkflowPayloadFieldDay{..} = JSON.object $ omitNothing
[ "tag" JSON..= WPFDay'
, "label" JSON..= wpfdLabel
, "tooltip" JSON..= wpfdTooltip
, "default" JSON..= wpfdDefault
, "optional" JSON..= wpfdOptional
]
toJSON (WorkflowPayloadFieldFile{..}) = JSON.object $ omitNothing
toJSON WorkflowPayloadFieldFile{..} = JSON.object $ omitNothing
[ "tag" JSON..= WPFFile'
, "label" JSON..= wpffLabel
, "tooltip" JSON..= wpffTooltip
, "config" JSON..= wpffConfig
, "optional" JSON..= wpffOptional
]
toJSON (WorkflowPayloadFieldUser{..}) = JSON.object $ omitNothing
toJSON WorkflowPayloadFieldUser{..} = JSON.object $ omitNothing
[ "tag" JSON..= WPFUser'
, "label" JSON..= wpfuLabel
, "tooltip" JSON..= wpfuTooltip
, "default" JSON..= wpfuDefault
, "optional" JSON..= wpfuOptional
]
toJSON (WorkflowPayloadFieldCaptureUser{}) = JSON.object
toJSON WorkflowPayloadFieldCaptureUser{} = JSON.object
[ "tag" JSON..= WPFCaptureUser'
]
toJSON (WorkflowPayloadFieldReference{..}) = JSON.object
toJSON WorkflowPayloadFieldReference{..} = JSON.object
[ "tag" JSON..= WPFReference'
, "target" JSON..= wpfrTarget
]
toJSON (WorkflowPayloadFieldMultiple{..}) = JSON.object
toJSON WorkflowPayloadFieldMultiple{..} = JSON.object
[ "tag" JSON..= WPFMultiple'
, "label" JSON..= wpfmLabel
, "tooltip" JSON..= wpfmTooltip

View File

@ -47,6 +47,9 @@ import Control.Lens.Extras (is)
import Control.Monad.Fail (fail)
{-# ANN module ("HLint: ignore Use newtype instead of data"::String) #-}
data I18n a = I18n
{ i18nFallback :: a
, i18nFallbackLang :: Maybe Lang

View File

@ -1,5 +1,3 @@
{-# OPTIONS -Wno-error=redundant-constraints #-}
module Utils.Workflow
( _DBWorkflowScope
, fromRouteWorkflowScope, toRouteWorkflowScope

View File

@ -8,6 +8,9 @@ import Import.NoFoundation
import qualified Data.Set as Set
import qualified Data.Map as Map
{-# ANN module ("HLint: ignore Use newtype instead of data"::String) #-}
data WorkflowGraphLinterIssue
= WGLUnknownGraphNodeLabel WorkflowGraphNodeLabel

View File

@ -1331,6 +1331,42 @@ fillDb = do
, workflowInstanceDescriptionDescription = Just "Hier können Sie Abschlussarbeiten bei der Prüfungsverwaltung angemeldet werden, der relevante Student die Arbeit digital abgeben und im Anschluss auch die Benotung an die Prüfungsverwaltung übermittelt werden."
}
do
workflowDefinitionGraph <- Yaml.decodeFileThrow $ testdataDir </> "recognitions.yaml"
for_ (lintWorkflowGraph workflowDefinitionGraph) $ mapM_ throwM
let
recognitionsWorkflowDef = WorkflowDefinition{..}
where workflowDefinitionInstanceCategory = Just "recognitions"
workflowDefinitionName = "recognitions"
workflowDefinitionScope = WSSchool'
wdId <- insert recognitionsWorkflowDef
insert_ WorkflowDefinitionDescription
{ workflowDefinitionDescriptionDefinition = wdId
, workflowDefinitionDescriptionLanguage = "de-de-formal"
, workflowDefinitionDescriptionTitle = "Anerkennungen"
, workflowDefinitionDescriptionDescription = Just "Erlaubt Anerkennungen von Leistungen in Uni2work zu verwalten"
}
insert_ WorkflowDefinitionInstanceDescription
{ workflowDefinitionInstanceDescriptionDefinition = wdId
, workflowDefinitionInstanceDescriptionLanguage = "de-de-formal"
, workflowDefinitionInstanceDescriptionTitle = "Anerekennungen"
, workflowDefinitionInstanceDescriptionDescription = Nothing
}
let
recognitionsWorkflowInst = WorkflowInstance{..}
where workflowInstanceDefinition = Just wdId
workflowInstanceGraph = workflowDefinitionGraph
workflowInstanceScope = WSSchool $ unSchoolKey ifi
workflowInstanceName = workflowDefinitionName recognitionsWorkflowDef
workflowInstanceCategory = workflowDefinitionInstanceCategory recognitionsWorkflowDef
wiId <- insert recognitionsWorkflowInst
insert_ WorkflowInstanceDescription
{ workflowInstanceDescriptionInstance = wiId
, workflowInstanceDescriptionLanguage = "de-de-formal"
, workflowInstanceDescriptionTitle = "Anerkennungen"
, workflowInstanceDescriptionDescription = Nothing
}
forM_ universeF $ \changelogItem -> do
let ptn = "templates/i18n/changelog/" <> unpack (toPathPiece changelogItem) <> ".*"
files <- liftIO $ glob ptn

739
testdata/recognitions.yaml vendored Normal file
View File

@ -0,0 +1,739 @@
"init":
final: false
messages: []
edges:
"antrag freischalten":
display-label: "Einzelnen Anerkennungsantrag freischalten"
mode: initial
actors:
- &pruefungsamt
tag: authorized
authorized: { "dnf-terms": [[{"tag": "variable", "var": "exam-office"}]] }
view-actor:
- *pruefungsamt
form:
"student":
- tag: user
label: "Student"
tooltip: null
default: null
optional: false
viewers:
display-label: "Antrag freigeschaltet"
viewers:
- *pruefungsamt
- &student
tag: payload-reference
payload-label: "student"
payload-view: &payload-view-init
"student":
viewers:
- *pruefungsamt
display-label: "Student"
"itkompetenz antrag, student":
final: false
messages: &messages-antrag-student
- <<: &message-antrag-student
viewers:
- *student
status: warning
content: "Sie können Ihren Antrag aktuell beliebig editieren. Sie müssen ihn jedoch „zur Begutachtung einreichen“ bevor er von der Prüfungsverwaltung bearbeitet wird. Danach können Sie ihn erst wieder editieren, falls die Prüfungsverwaltung den Antrag an Sie zurück gibt."
edges:
"itkompetenz beantragen":
mode: manual
display-label: "Eine Veranstaltung als IT-Kompetenz anerkennen (nur Informatik-Hauptfach Bachelor)"
source: "init"
actors:
- *student
view-actor:
- *pruefungsamt
- *student
form: &itkompetenz-form
"titel": &titel-form
- "1":
tag: text
label: "Titelvorschlag für Veranstaltung"
tooltip: null
default: null
optional: false
"titel, englisch": &entitel-form
- "2":
tag: text
label: "Titelvorschlag für Verastaltung, auf Englisch"
tooltip: null
default: null
optional: false
"beleg": &beleg-form
- "3": &beleg-field
tag: file
label: "Bescheid über durchgeführte Tätigkeit"
tooltip: null
optional: false
config:
unpack-zips:
default: false
force: true
multiple: false
all-empty-ok: false
max-file-size: 5242880
"itkompetenz editieren":
mode: manual
display-label: "Antrag bearbeiten (IT-Kompetenz)"
source: "itkompetenz antrag, student"
actors:
- *student
view-actor:
- *pruefungsamt
- *student
form: *itkompetenz-form
"itkompetenz antrag zurueck":
mode: manual
display-label: "Antrag an Student zurück geben"
source: "itkompetenz antrag, pa"
actors:
- *pruefungsamt
view-actor:
- *pruefungsamt
form: &itkompetenz-notizen-form
"titel": *titel-form
"titel, englisch": *entitel-form
"notizen": &notizen-form
- "4":
tag: text
large: true
label: "Notizen / Anmerkungen"
tooltip: "Zur Kommunikation mit dem Studenten"
default: null
optional: false
viewers:
display-label: "Antrag in Bearbeitung (IT-Kompetenz)"
viewers:
- *student
- *pruefungsamt
payload-view: &payload-view-itkompetenz-notizen
<<: &payload-view-itkompetenz
<<: *payload-view-init
"titel":
viewers:
- *student
- *pruefungsamt
display-label: "Titel"
"titel, englisch":
viewers:
- *student
- *pruefungsamt
display-label: "Titel, Englisch"
"beleg":
viewers:
- *student
- *pruefungsamt
display-label: "Beleg"
"notizen":
viewers:
- *student
- *pruefungsamt
display-label: "Notizen / Anmerkungen"
"itkompetenz antrag, pa":
final: false
messages: []
viewers:
display-label: "Antrag in Begutachtung (IT-Kompetenz)"
viewers:
- *student
- *pruefungsamt
edges:
"itkompetenz einreichen":
mode: manual
display-label: "Antrag zur Begutachtung einreichen"
source: "itkompetenz antrag, student"
actors:
- *student
view-actor:
- *pruefungsamt
- *student
form: {}
payload-view: *payload-view-itkompetenz-notizen
"itkompetenz ok":
final: true
messages: []
edges:
"itkompetenz akzeptieren":
mode: manual
display-label: "Antrag genehmigen"
source: "itkompetenz antrag, pa"
actors:
- *pruefungsamt
view-actor:
- *pruefungsamt
form:
"titel": *titel-form
"titel, englisch": *entitel-form
viewers:
display-label: "Antrag genehmigt (IT-Kompetenz)"
viewers:
- *student
- *pruefungsamt
payload-view: *payload-view-itkompetenz
"itkompetenz abgelehnt":
final: true
messages: []
edges:
"itkompetenz ablehnen":
mode: manual
display-label: "Antrag ablehnen"
source: "itkompetenz antrag, pa"
actors:
- *pruefungsamt
view-actor:
- *pruefungsamt
form: {}
viewers:
display-label: "Antrag abgelehnt (IT-Kompetenz)"
viewers:
- *student
- *pruefungsamt
payload-view: *payload-view-itkompetenz
"medienkompetenz antrag, student":
final: false
messages: *messages-antrag-student
edges:
"medienkompetenz beantragen":
mode: manual
display-label: "Eine Veranstaltung als Medienkompetenz anerkennen (nur Medieninformatik-Hauptfach Bachelor)"
source: "init"
actors:
- *student
view-actor:
- *pruefungsamt
- *student
form: &medienkompetenz-form
"titel": *titel-form
"titel, englisch": *entitel-form
"beleg": *beleg-form
"medienkompetenz editieren":
mode: manual
display-label: "Antrag bearbeiten (Medienkompetenz)"
source: "medienkompetenz antrag, student"
actors:
- *student
view-actor:
- *pruefungsamt
- *student
form: *medienkompetenz-form
"medienkompetenz antrag zurueck":
mode: manual
display-label: "Antrag an Student zurück geben"
source: "medienkompetenz antrag, pa"
actors:
- *pruefungsamt
view-actor:
- *pruefungsamt
form: &medienkompetenz-notizen-form
"titel": *titel-form
"titel, englisch": *entitel-form
"notizen": *notizen-form
viewers:
display-label: "Antrag in Bearbeitung (Medienkompetenz)"
viewers:
- *student
- *pruefungsamt
payload-view: &payload-view-medienkompetenz-notizen
<<: &payload-view-medienkompetenz
<<: *payload-view-init
"titel":
viewers:
- *student
- *pruefungsamt
display-label: "Titel"
"titel, englisch":
viewers:
- *student
- *pruefungsamt
display-label: "Titel, Englisch"
"beleg":
viewers:
- *student
- *pruefungsamt
display-label: "Beleg"
"notizen":
viewers:
- *student
- *pruefungsamt
display-label: "Notizen / Anmerkungen"
"medienkompetenz antrag, pa":
final: false
messages: []
viewers:
display-label: "Antrag in Begutachtung (Medienkompetenz)"
viewers:
- *student
- *pruefungsamt
edges:
"medienkompetenz einreichen":
mode: manual
display-label: "Antrag zur Begutachtung einreichen"
source: "medienkompetenz antrag, student"
actors:
- *student
view-actor:
- *pruefungsamt
- *student
form: {}
payload-view: *payload-view-medienkompetenz-notizen
"medienkompetenz ok":
final: true
messages: []
edges:
"medienkompetenz akzeptieren":
mode: manual
display-label: "Antrag genehmigen"
source: "medienkompetenz antrag, pa"
actors:
- *pruefungsamt
view-actor:
- *pruefungsamt
form:
"titel": *titel-form
"titel, englisch": *entitel-form
viewers:
display-label: "Antrag genehmigt (Medienkompetenz)"
viewers:
- *student
- *pruefungsamt
payload-view: *payload-view-medienkompetenz
"medienkompetenz abgelehnt":
final: true
messages: []
edges:
"medienkompetenz ablehnen":
mode: manual
display-label: "Antrag ablehnen"
source: "medienkompetenz antrag, pa"
actors:
- *pruefungsamt
view-actor:
- *pruefungsamt
form: {}
viewers:
display-label: "Antrag abgelehnt (Medienkompetenz)"
viewers:
- *student
- *pruefungsamt
payload-view: *payload-view-medienkompetenz
"tutor antrag, student":
final: false
messages: *messages-antrag-student
edges:
"tutor beantragen":
mode: manual
display-label: "Tutortätigkeit als soziale und persönliche Kompetenz anerkennen lassen (nur (Medien-)Informatik Bachelor)"
source: "init"
actors:
- *student
view-actor:
- *pruefungsamt
- *student
form: &tutor-form
"institut": &institut-form
- "1":
tag: text
label: "Institut"
tooltip: "An welchem Institut der LMU wurde die Tutortätigkeit ausgeübt?"
default: null
optional: false
"tutorbeleg": &tutorbeleg-form
- "2":
tag: text
label: "Veranstaltungswebseite"
tooltip: "Link zu einer offiziellen Webseite der Veranstaltung, die Sie als Tutor führt (z.B. in Uni2work)"
optional: false
- "3":
<<: *beleg-field
label: "Bestätigung"
tooltip: "Bestätigung der durchgeführten Tutortätigkeit (falls aus Webseite nicht ersichtlich)"
optional: false
"tutor editieren":
mode: manual
display-label: "Antrag bearbeiten (Tutor)"
source: "tutor antrag, student"
actors:
- *student
view-actor:
- *pruefungsamt
- *student
form: *tutor-form
"tutor antrag zurueck":
mode: manual
display-label: "Antrag an Student zurück geben"
source: "tutor antrag, pa"
actors:
- *pruefungsamt
view-actor:
- *pruefungsamt
form: &tutor-notizen-form
"institut": *institut-form
"tutorbeleg": *tutorbeleg-form
"notizen": *notizen-form
viewers:
display-label: "Antrag in Bearbeitung (Tutor)"
viewers:
- *student
- *pruefungsamt
payload-view: &payload-view-tutor-notizen
<<: &payload-view-tutor
<<: *payload-view-init
"institut":
viewers:
- *student
- *pruefungsamt
display-label: "Institut"
"tutorbeleg":
viewers:
- *student
- *pruefungsamt
display-label: "Beleg"
"notizen":
viewers:
- *student
- *pruefungsamt
display-label: "Notizen / Anmerkungen"
"tutor antrag, pa":
final: false
messages: []
viewers:
display-label: "Antrag in Begutachtung (Tutor)"
viewers:
- *student
- *pruefungsamt
edges:
"tutor einreichen":
mode: manual
display-label: "Antrag zur Begutachtung einreichen"
source: "tutor antrag, student"
actors:
- *student
view-actor:
- *pruefungsamt
- *student
form: {}
payload-view: *payload-view-tutor-notizen
"tutor ok":
final: true
messages: []
edges:
"tutor akzeptieren":
mode: manual
display-label: "Antrag genehmigen"
source: "tutor antrag, pa"
actors:
- *pruefungsamt
view-actor:
- *pruefungsamt
form:
"institut": *institut-form
viewers:
display-label: "Antrag genehmigt (Tutor)"
viewers:
- *student
- *pruefungsamt
payload-view: *payload-view-tutor
"tutor abgelehnt":
final: true
messages: []
edges:
"tutor ablehnen":
mode: manual
display-label: "Antrag ablehnen"
source: "tutor antrag, pa"
actors:
- *pruefungsamt
view-actor:
- *pruefungsamt
form: {}
viewers:
display-label: "Antrag abgelehnt (Tutor)"
viewers:
- *student
- *pruefungsamt
payload-view: *payload-view-tutor
"sozialekompetenz antrag, student":
final: false
messages: *messages-antrag-student
edges:
"sozialekompetenz beantragen":
mode: manual
display-label: "Tätigkeit (nicht Tutortätigkeit) als soziale und persönliche Kompetenz anerkennen lassen (nur (Medien-)Informatik Bachelor)"
source: "init"
actors:
- *student
view-actor:
- *pruefungsamt
- *student
form: &sozialekompetenz-form
"titel": *titel-form
"titel, englisch": *entitel-form
"beleg": *beleg-form
"sozialekompetenz editieren":
mode: manual
display-label: "Antrag bearbeiten (Sozialekompetenz)"
source: "sozialekompetenz antrag, student"
actors:
- *student
view-actor:
- *pruefungsamt
- *student
form: *sozialekompetenz-form
"sozialekompetenz antrag zurueck":
mode: manual
display-label: "Antrag an Student zurück geben"
source: "sozialekompetenz antrag, pa"
actors:
- *pruefungsamt
view-actor:
- *pruefungsamt
form: &sozialekompetenz-notizen-form
"titel": *titel-form
"titel, englisch": *entitel-form
"notizen": *notizen-form
viewers:
display-label: "Antrag in Bearbeitung (Sozialekompetenz)"
viewers:
- *student
- *pruefungsamt
payload-view: &payload-view-sozialekompetenz-notizen
<<: &payload-view-sozialekompetenz
<<: *payload-view-init
"titel":
viewers:
- *student
- *pruefungsamt
display-label: "Titel"
"titel, englisch":
viewers:
- *student
- *pruefungsamt
display-label: "Titel, Englisch"
"beleg":
viewers:
- *student
- *pruefungsamt
display-label: "Beleg"
"notizen":
viewers:
- *student
- *pruefungsamt
display-label: "Notizen / Anmerkungen"
"sozialekompetenz antrag, pa":
final: false
messages: []
viewers:
display-label: "Antrag in Begutachtung (Sozialekompetenz)"
viewers:
- *student
- *pruefungsamt
edges:
"sozialekompetenz einreichen":
mode: manual
display-label: "Antrag zur Begutachtung einreichen"
source: "sozialekompetenz antrag, student"
actors:
- *student
view-actor:
- *pruefungsamt
- *student
form: {}
payload-view: *payload-view-sozialekompetenz-notizen
"sozialekompetenz ok":
final: true
messages: []
edges:
"sozialekompetenz akzeptieren":
mode: manual
display-label: "Antrag genehmigen"
source: "sozialekompetenz antrag, pa"
actors:
- *pruefungsamt
view-actor:
- *pruefungsamt
form:
"titel": *titel-form
"titel, englisch": *entitel-form
viewers:
display-label: "Antrag genehmigt (Sozialekompetenz)"
viewers:
- *student
- *pruefungsamt
payload-view: *payload-view-sozialekompetenz
"sozialekompetenz abgelehnt":
final: true
messages: []
edges:
"sozialekompetenz ablehnen":
mode: manual
display-label: "Antrag ablehnen"
source: "sozialekompetenz antrag, pa"
actors:
- *pruefungsamt
view-actor:
- *pruefungsamt
form: {}
viewers:
display-label: "Antrag abgelehnt (Sozialekompetenz)"
viewers:
- *student
- *pruefungsamt
payload-view: *payload-view-sozialekompetenz
"englisch antrag, student":
final: false
messages: *messages-antrag-student
edges:
"englisch beantragen":
mode: manual
display-label: "Note aus dem e-Xplore Technical Englisch Kurs melden"
source: "init"
actors:
- *student
view-actor:
- *pruefungsamt
- *student
form: &englisch-form
"note": &note-form
- "1": &note-field
tag: text
label: "Note"
placeholder: "Note"
optional: false
"datum": &datum-form
- "2": &datum-field
tag: day
label: "Datum"
optional: false
"englischbeleg": &englischbeleg-form
- "3": &englischbeleg-field
tag: file
label: "Dokument"
tooltip: "Mindestens die Seite mit Note und Datum"
optional: false
config:
unpack-zips:
default: true
force: true
multiple: true
all-empty-ok: false
max-file-size: 5242880
"englisch editieren":
mode: manual
display-label: "Antrag bearbeiten (Englisch)"
source: "englisch antrag, student"
actors:
- *student
view-actor:
- *pruefungsamt
- *student
form: *englisch-form
"englisch antrag zurueck":
mode: manual
display-label: "Antrag an Student zurück geben"
source: "englisch antrag, pa"
actors:
- *pruefungsamt
view-actor:
- *pruefungsamt
form: &englisch-notizen-form
"note": *note-form
"datum": *datum-form
"englischbeleg": *englischbeleg-form
"notizen": *notizen-form
viewers:
display-label: "Antrag in Bearbeitung (Englisch)"
viewers:
- *student
- *pruefungsamt
payload-view: &payload-view-englisch-notizen
<<: &payload-view-englisch
<<: *payload-view-init
"note":
viewers:
- *student
- *pruefungsamt
display-label: "Note"
"datum":
viewers:
- *student
- *pruefungsamt
display-label: "Datum"
"englischbeleg":
viewers:
- *student
- *pruefungsamt
display-label: "Beleg"
"notizen":
viewers:
- *student
- *pruefungsamt
display-label: "Notizen / Anmerkungen"
"englisch antrag, pa":
final: false
messages: []
viewers:
display-label: "Antrag in Begutachtung (Englisch)"
viewers:
- *student
- *pruefungsamt
edges:
"englisch einreichen":
mode: manual
display-label: "Antrag zur Begutachtung einreichen"
source: "englisch antrag, student"
actors:
- *student
view-actor:
- *pruefungsamt
- *student
form: {}
payload-view: *payload-view-englisch-notizen
"englisch ok":
final: true
messages: []
edges:
"englisch akzeptieren":
mode: manual
display-label: "Antrag genehmigen"
source: "englisch antrag, pa"
actors:
- *pruefungsamt
view-actor:
- *pruefungsamt
form:
"note": *note-form
"datum": *datum-form
viewers:
display-label: "Antrag genehmigt (Englisch)"
viewers:
- *student
- *pruefungsamt
payload-view: *payload-view-englisch
"englisch abgelehnt":
final: true
messages: []
edges:
"englisch ablehnen":
mode: manual
display-label: "Antrag ablehnen"
source: "englisch antrag, pa"
actors:
- *pruefungsamt
view-actor:
- *pruefungsamt
form: {}
viewers:
display-label: "Antrag abgelehnt (Englisch)"
viewers:
- *student
- *pruefungsamt
payload-view: *payload-view-englisch

1276
testdata/theses.yaml vendored

File diff suppressed because it is too large Load Diff