diff --git a/shared-common/src/Shared/Common/Util/Aeson.hs b/shared-common/src/Shared/Common/Util/Aeson.hs index eaa6a8fc9..c65641341 100644 --- a/shared-common/src/Shared/Common/Util/Aeson.hs +++ b/shared-common/src/Shared/Common/Util/Aeson.hs @@ -52,6 +52,7 @@ jsonSpecialFields "qiId" = "id" jsonSpecialFields "sId" = "id" jsonSpecialFields "tId" = "id" jsonSpecialFields "aData" = "data" +jsonSpecialFields "adData" = "data" jsonSpecialFields "seData" = "data" jsonSpecialFields "scData" = "data" jsonSpecialFields "sqData" = "data" @@ -66,6 +67,7 @@ jsonSpecialFields "oRole" = "role" jsonSpecialFields "uRole" = "role" jsonSpecialFields "sValue" = "value" jsonSpecialFields "aValue" = "value" +jsonSpecialFields "fValue" = "value" jsonSpecialFields "mcValue" = "value" jsonSpecialFields "ilValue" = "value" jsonSpecialFields "iValue" = "value" diff --git a/wizard-common/src/WizardLib/KnowledgeModel/Api/Resource/Event/QuestionEventJM.hs b/wizard-common/src/WizardLib/KnowledgeModel/Api/Resource/Event/QuestionEventJM.hs index c0a514692..ed3baa10c 100644 --- a/wizard-common/src/WizardLib/KnowledgeModel/Api/Resource/Event/QuestionEventJM.hs +++ b/wizard-common/src/WizardLib/KnowledgeModel/Api/Resource/Event/QuestionEventJM.hs @@ -21,6 +21,7 @@ instance FromJSON AddQuestionEvent where "ValueQuestion" -> parseJSON (Object o) >>= \event -> return (AddValueQuestionEvent' event) "IntegrationQuestion" -> parseJSON (Object o) >>= \event -> return (AddIntegrationQuestionEvent' event) "ItemSelectQuestion" -> parseJSON (Object o) >>= \event -> return (AddItemSelectQuestionEvent' event) + "FileQuestion" -> parseJSON (Object o) >>= \event -> return (AddFileQuestionEvent' event) _ -> fail "One of the events has unsupported questionType" parseJSON _ = mzero @@ -66,6 +67,13 @@ instance FromJSON AddItemSelectQuestionEvent where instance ToJSON AddItemSelectQuestionEvent where toJSON = toJSONWithAdditionalData [("questionType", "ItemSelectQuestion")] +-- -------------------------------------------- +instance FromJSON AddFileQuestionEvent where + parseJSON = genericParseJSON jsonOptions + +instance ToJSON AddFileQuestionEvent where + toJSON = toJSONWithAdditionalData [("questionType", "FileQuestion")] + -- -------------------------------------------- -- -------------------------------------------- instance ToJSON EditQuestionEvent where @@ -81,6 +89,7 @@ instance FromJSON EditQuestionEvent where "ValueQuestion" -> parseJSON (Object o) >>= \event -> return (EditValueQuestionEvent' event) "IntegrationQuestion" -> parseJSON (Object o) >>= \event -> return (EditIntegrationQuestionEvent' event) "ItemSelectQuestion" -> parseJSON (Object o) >>= \event -> return (EditItemSelectQuestionEvent' event) + "FileQuestion" -> parseJSON (Object o) >>= \event -> return (EditFileQuestionEvent' event) _ -> fail "One of the events has unsupported questionType" parseJSON _ = mzero @@ -126,6 +135,13 @@ instance FromJSON EditItemSelectQuestionEvent where instance ToJSON EditItemSelectQuestionEvent where toJSON = toJSONWithAdditionalData [("questionType", "ItemSelectQuestion")] +-- -------------------------------------------- +instance FromJSON EditFileQuestionEvent where + parseJSON = genericParseJSON jsonOptions + +instance ToJSON EditFileQuestionEvent where + toJSON = toJSONWithAdditionalData [("questionType", "FileQuestion")] + -- -------------------------------------------- -- -------------------------------------------- instance FromJSON DeleteQuestionEvent where diff --git a/wizard-common/src/WizardLib/KnowledgeModel/Api/Resource/Event/QuestionEventSM.hs b/wizard-common/src/WizardLib/KnowledgeModel/Api/Resource/Event/QuestionEventSM.hs index 686521b9a..c42d68fdf 100644 --- a/wizard-common/src/WizardLib/KnowledgeModel/Api/Resource/Event/QuestionEventSM.hs +++ b/wizard-common/src/WizardLib/KnowledgeModel/Api/Resource/Event/QuestionEventSM.hs @@ -30,6 +30,9 @@ instance ToSchema AddIntegrationQuestionEvent where instance ToSchema AddItemSelectQuestionEvent where declareNamedSchema = toSwaggerWithType "eventType" a_km1_ch3_q13' +instance ToSchema AddFileQuestionEvent where + declareNamedSchema = toSwaggerWithType "eventType" a_km1_ch3_q14' + -- -------------------------------------------- -- -------------------------------------------- instance ToSchema EditQuestionEvent @@ -52,6 +55,9 @@ instance ToSchema EditIntegrationQuestionEvent where instance ToSchema EditItemSelectQuestionEvent where declareNamedSchema = toSwaggerWithType "eventType" e_km1_ch3_q13' +instance ToSchema EditFileQuestionEvent where + declareNamedSchema = toSwaggerWithType "eventType" e_km1_ch3_q14' + -- -------------------------------------------- -- -------------------------------------------- instance ToSchema DeleteQuestionEvent where diff --git a/wizard-common/src/WizardLib/KnowledgeModel/Api/Resource/KnowledgeModel/KnowledgeModelJM.hs b/wizard-common/src/WizardLib/KnowledgeModel/Api/Resource/KnowledgeModel/KnowledgeModelJM.hs index 71aa957f4..157fef5c3 100644 --- a/wizard-common/src/WizardLib/KnowledgeModel/Api/Resource/KnowledgeModel/KnowledgeModelJM.hs +++ b/wizard-common/src/WizardLib/KnowledgeModel/Api/Resource/KnowledgeModel/KnowledgeModelJM.hs @@ -48,6 +48,7 @@ instance FromJSON Question where "ValueQuestion" -> parseJSON (Object o) >>= \event -> return (ValueQuestion' event) "IntegrationQuestion" -> parseJSON (Object o) >>= \event -> return (IntegrationQuestion' event) "ItemSelectQuestion" -> parseJSON (Object o) >>= \event -> return (ItemSelectQuestion' event) + "FileQuestion" -> parseJSON (Object o) >>= \event -> return (FileQuestion' event) _ -> fail "One of the questions has unsupported questionType" parseJSON _ = mzero @@ -93,6 +94,13 @@ instance ToJSON ItemSelectQuestion where instance FromJSON ItemSelectQuestion where parseJSON = genericParseJSON (jsonOptionsWithTypeField "questionType") +-- -------------------------------------------------------------------- +instance ToJSON FileQuestion where + toJSON = genericToJSON (jsonOptionsWithTypeField "questionType") + +instance FromJSON FileQuestion where + parseJSON = genericParseJSON (jsonOptionsWithTypeField "questionType") + -- -------------------------------------------------------------------- -- -------------------------------------------------------------------- instance ToJSON Answer where diff --git a/wizard-common/src/WizardLib/KnowledgeModel/Api/Resource/KnowledgeModel/KnowledgeModelSM.hs b/wizard-common/src/WizardLib/KnowledgeModel/Api/Resource/KnowledgeModel/KnowledgeModelSM.hs index c68052ae5..fd82c60cb 100644 --- a/wizard-common/src/WizardLib/KnowledgeModel/Api/Resource/KnowledgeModel/KnowledgeModelSM.hs +++ b/wizard-common/src/WizardLib/KnowledgeModel/Api/Resource/KnowledgeModel/KnowledgeModelSM.hs @@ -65,6 +65,10 @@ instance ToSchema IntegrationQuestion where instance ToSchema ItemSelectQuestion where declareNamedSchema = toSwaggerWithType "questionType" question13 +-- -------------------------------------------------------------------- +instance ToSchema FileQuestion where + declareNamedSchema = toSwaggerWithType "questionType" question14 + -- -------------------------------------------------------------------- -- -------------------------------------------------------------------- instance ToSchema Answer where diff --git a/wizard-common/src/WizardLib/KnowledgeModel/Database/Migration/Development/Event/Data/Events.hs b/wizard-common/src/WizardLib/KnowledgeModel/Database/Migration/Development/Event/Data/Events.hs index acc3e6337..a522bdb07 100644 --- a/wizard-common/src/WizardLib/KnowledgeModel/Database/Migration/Development/Event/Data/Events.hs +++ b/wizard-common/src/WizardLib/KnowledgeModel/Database/Migration/Development/Event/Data/Events.hs @@ -321,6 +321,25 @@ a_km1_ch3_q13 = , createdAt = dt' 2018 1 21 } +a_km1_ch3_q14' :: AddQuestionEvent +a_km1_ch3_q14' = AddFileQuestionEvent' a_km1_ch3_q14 + +a_km1_ch3_q14 :: AddFileQuestionEvent +a_km1_ch3_q14 = + AddFileQuestionEvent + { uuid = u' "cdd54bfa-b2de-4ab3-9022-bc512cfa297f" + , parentUuid = chapter3.uuid + , entityUuid = question14.uuid + , title = question14.title + , text = question14.text + , requiredPhaseUuid = question14.requiredPhaseUuid + , annotations = question14.annotations + , tagUuids = question14.tagUuids + , maxSize = question14.maxSize + , fileTypes = question14.fileTypes + , createdAt = dt' 2018 1 21 + } + e_km1_ch1_q1' :: EditQuestionEvent e_km1_ch1_q1' = EditValueQuestionEvent' e_km1_ch1_q1 @@ -531,7 +550,7 @@ e_km1_ch3_q13 = EditItemSelectQuestionEvent { uuid = u' "f95ace16-9a2c-4f66-b22f-e419e5014c58" , parentUuid = chapter3.uuid - , entityUuid = question2.uuid + , entityUuid = question13Edited.uuid , title = ChangedValue $ question13Edited.title , text = ChangedValue $ question13Edited.text , requiredPhaseUuid = ChangedValue $ question13Edited.requiredPhaseUuid @@ -543,6 +562,27 @@ e_km1_ch3_q13 = , createdAt = dt' 2018 1 21 } +e_km1_ch3_q14' :: EditQuestionEvent +e_km1_ch3_q14' = EditFileQuestionEvent' e_km1_ch3_q14 + +e_km1_ch3_q14 :: EditFileQuestionEvent +e_km1_ch3_q14 = + EditFileQuestionEvent + { uuid = u' "cd144dd9-c722-400f-9972-2642177dee06" + , parentUuid = chapter3.uuid + , entityUuid = question14Edited.uuid + , title = ChangedValue question14Edited.title + , text = ChangedValue question14Edited.text + , requiredPhaseUuid = ChangedValue question14Edited.requiredPhaseUuid + , annotations = ChangedValue question14Edited.annotations + , tagUuids = ChangedValue question14Edited.tagUuids + , expertUuids = ChangedValue question14Edited.expertUuids + , referenceUuids = ChangedValue question14Edited.referenceUuids + , maxSize = ChangedValue question14Edited.maxSize + , fileTypes = ChangedValue question14Edited.fileTypes + , createdAt = dt' 2018 1 21 + } + d_km1_ch1_q1 :: DeleteQuestionEvent d_km1_ch1_q1 = DeleteQuestionEvent diff --git a/wizard-common/src/WizardLib/KnowledgeModel/Database/Migration/Development/KnowledgeModel/Data/Chapters.hs b/wizard-common/src/WizardLib/KnowledgeModel/Database/Migration/Development/KnowledgeModel/Data/Chapters.hs index a19f1ab6b..b1dcb28c4 100644 --- a/wizard-common/src/WizardLib/KnowledgeModel/Database/Migration/Development/KnowledgeModel/Data/Chapters.hs +++ b/wizard-common/src/WizardLib/KnowledgeModel/Database/Migration/Development/KnowledgeModel/Data/Chapters.hs @@ -75,7 +75,7 @@ chapter3 = , title = "Data Capture/Measurement" , text = Just "" , annotations = [] - , questionUuids = [question9.uuid, question10.uuid, question11.uuid, question12.uuid, question13.uuid] + , questionUuids = [question9.uuid, question10.uuid, question11.uuid, question12.uuid, question13.uuid, question14.uuid] } chapter4WithoutQuestions :: Chapter diff --git a/wizard-common/src/WizardLib/KnowledgeModel/Database/Migration/Development/KnowledgeModel/Data/KnowledgeModels.hs b/wizard-common/src/WizardLib/KnowledgeModel/Database/Migration/Development/KnowledgeModel/Data/KnowledgeModels.hs index d4a224c31..d99a322a6 100644 --- a/wizard-common/src/WizardLib/KnowledgeModel/Database/Migration/Development/KnowledgeModel/Data/KnowledgeModels.hs +++ b/wizard-common/src/WizardLib/KnowledgeModel/Database/Migration/Development/KnowledgeModel/Data/KnowledgeModels.hs @@ -43,6 +43,7 @@ km1 = , question11' , question12' , question13' + , question14' ] , answers = toMap @@ -138,6 +139,7 @@ km1WithQ4Plain = , question11' , question12' , question13' + , question14' ] , answers = toMap @@ -198,6 +200,7 @@ km1WithQ4 = , question11' , question12' , question13' + , question14' ] , answers = toMap diff --git a/wizard-common/src/WizardLib/KnowledgeModel/Database/Migration/Development/KnowledgeModel/Data/Questions.hs b/wizard-common/src/WizardLib/KnowledgeModel/Database/Migration/Development/KnowledgeModel/Data/Questions.hs index 1a75c4810..62b5adab1 100644 --- a/wizard-common/src/WizardLib/KnowledgeModel/Database/Migration/Development/KnowledgeModel/Data/Questions.hs +++ b/wizard-common/src/WizardLib/KnowledgeModel/Database/Migration/Development/KnowledgeModel/Data/Questions.hs @@ -561,3 +561,39 @@ question13Edited = , expertUuids = [] , listQuestionUuid = Just q4_it1_question5.uuid } + +question14' :: Question +question14' = FileQuestion' question14 + +question14 :: FileQuestion +question14 = + FileQuestion + { uuid = u' "00000000-0000-0000-0000-000000000f14" + , title = "Fourteen Question" + , text = Just "Some non-funny description" + , requiredPhaseUuid = Nothing + , annotations = [] + , tagUuids = [tagBioInformatic.uuid] + , referenceUuids = [] + , expertUuids = [] + , maxSize = Just 20000 + , fileTypes = Just "application/json" + } + +question14Edited' :: Question +question14Edited' = FileQuestion' question14Edited + +question14Edited :: FileQuestion +question14Edited = + FileQuestion + { uuid = question14.uuid + , title = "EDITED: Fourteen Question" + , text = Just "EDITED: Some non-funny description" + , requiredPhaseUuid = Just $ phase2.uuid + , annotations = [] + , tagUuids = [tagBioInformatic.uuid] + , referenceUuids = [] + , expertUuids = [] + , maxSize = Just 40000 + , fileTypes = Just "text/html" + } diff --git a/wizard-common/src/WizardLib/KnowledgeModel/Database/Migration/Development/Package/Data/Packages.hs b/wizard-common/src/WizardLib/KnowledgeModel/Database/Migration/Development/Package/Data/Packages.hs index 7bdc3b910..9766829fa 100644 --- a/wizard-common/src/WizardLib/KnowledgeModel/Database/Migration/Development/Package/Data/Packages.hs +++ b/wizard-common/src/WizardLib/KnowledgeModel/Database/Migration/Development/Package/Data/Packages.hs @@ -250,6 +250,7 @@ germanyPackage = , AddChoiceEvent' a_km1_ch3_q11_cho2 , AddQuestionEvent' a_km1_ch3_q12' , AddQuestionEvent' a_km1_ch3_q13' + , AddQuestionEvent' a_km1_ch3_q14' ] , nonEditable = False , tenantUuid = U.nil diff --git a/wizard-common/src/WizardLib/KnowledgeModel/Model/Event/Question/QuestionEvent.hs b/wizard-common/src/WizardLib/KnowledgeModel/Model/Event/Question/QuestionEvent.hs index 136a8eda6..9d4089f8a 100644 --- a/wizard-common/src/WizardLib/KnowledgeModel/Model/Event/Question/QuestionEvent.hs +++ b/wizard-common/src/WizardLib/KnowledgeModel/Model/Event/Question/QuestionEvent.hs @@ -16,6 +16,7 @@ data AddQuestionEvent | AddValueQuestionEvent' AddValueQuestionEvent | AddIntegrationQuestionEvent' AddIntegrationQuestionEvent | AddItemSelectQuestionEvent' AddItemSelectQuestionEvent + | AddFileQuestionEvent' AddFileQuestionEvent deriving (Show, Eq, Generic) data AddOptionsQuestionEvent = AddOptionsQuestionEvent @@ -100,6 +101,21 @@ data AddItemSelectQuestionEvent = AddItemSelectQuestionEvent } deriving (Show, Eq, Generic) +data AddFileQuestionEvent = AddFileQuestionEvent + { uuid :: U.UUID + , parentUuid :: U.UUID + , entityUuid :: U.UUID + , title :: String + , text :: Maybe String + , requiredPhaseUuid :: Maybe U.UUID + , annotations :: [MapEntry String String] + , tagUuids :: [U.UUID] + , maxSize :: Maybe Int + , fileTypes :: Maybe String + , createdAt :: UTCTime + } + deriving (Show, Eq, Generic) + -- -------------------------------------------- data EditQuestionEvent = EditOptionsQuestionEvent' EditOptionsQuestionEvent @@ -108,6 +124,7 @@ data EditQuestionEvent | EditValueQuestionEvent' EditValueQuestionEvent | EditIntegrationQuestionEvent' EditIntegrationQuestionEvent | EditItemSelectQuestionEvent' EditItemSelectQuestionEvent + | EditFileQuestionEvent' EditFileQuestionEvent deriving (Show, Eq, Generic) data EditOptionsQuestionEvent = EditOptionsQuestionEvent @@ -207,6 +224,23 @@ data EditItemSelectQuestionEvent = EditItemSelectQuestionEvent } deriving (Show, Eq, Generic) +data EditFileQuestionEvent = EditFileQuestionEvent + { uuid :: U.UUID + , parentUuid :: U.UUID + , entityUuid :: U.UUID + , title :: EventField String + , text :: EventField (Maybe String) + , requiredPhaseUuid :: EventField (Maybe U.UUID) + , annotations :: EventField [MapEntry String String] + , tagUuids :: EventField [U.UUID] + , expertUuids :: EventField [U.UUID] + , referenceUuids :: EventField [U.UUID] + , maxSize :: EventField (Maybe Int) + , fileTypes :: EventField (Maybe String) + , createdAt :: UTCTime + } + deriving (Show, Eq, Generic) + -- -------------------------------------------- data DeleteQuestionEvent = DeleteQuestionEvent { uuid :: U.UUID diff --git a/wizard-common/src/WizardLib/KnowledgeModel/Model/Event/Question/QuestionEventLenses.hs b/wizard-common/src/WizardLib/KnowledgeModel/Model/Event/Question/QuestionEventLenses.hs index 053a23b0a..bebe89fa7 100644 --- a/wizard-common/src/WizardLib/KnowledgeModel/Model/Event/Question/QuestionEventLenses.hs +++ b/wizard-common/src/WizardLib/KnowledgeModel/Model/Event/Question/QuestionEventLenses.hs @@ -14,12 +14,14 @@ instance HasUuid' AddQuestionEvent where getUuid (AddValueQuestionEvent' entity) = entity.uuid getUuid (AddIntegrationQuestionEvent' entity) = entity.uuid getUuid (AddItemSelectQuestionEvent' entity) = entity.uuid + getUuid (AddFileQuestionEvent' entity) = entity.uuid setUuid (AddListQuestionEvent' entity) newValue = AddListQuestionEvent' $ entity {uuid = newValue} setUuid (AddOptionsQuestionEvent' entity) newValue = AddOptionsQuestionEvent' $ entity {uuid = newValue} setUuid (AddMultiChoiceQuestionEvent' entity) newValue = AddMultiChoiceQuestionEvent' $ entity {uuid = newValue} setUuid (AddValueQuestionEvent' entity) newValue = AddValueQuestionEvent' $ entity {uuid = newValue} setUuid (AddIntegrationQuestionEvent' entity) newValue = AddIntegrationQuestionEvent' $ entity {uuid = newValue} setUuid (AddItemSelectQuestionEvent' entity) newValue = AddItemSelectQuestionEvent' $ entity {uuid = newValue} + setUuid (AddFileQuestionEvent' entity) newValue = AddFileQuestionEvent' $ entity {uuid = newValue} instance HasUuid' EditQuestionEvent where getUuid (EditOptionsQuestionEvent' entity) = entity.uuid @@ -28,12 +30,14 @@ instance HasUuid' EditQuestionEvent where getUuid (EditValueQuestionEvent' entity) = entity.uuid getUuid (EditIntegrationQuestionEvent' entity) = entity.uuid getUuid (EditItemSelectQuestionEvent' entity) = entity.uuid + getUuid (EditFileQuestionEvent' entity) = entity.uuid setUuid (EditOptionsQuestionEvent' entity) newValue = EditOptionsQuestionEvent' $ entity {uuid = newValue} setUuid (EditMultiChoiceQuestionEvent' entity) newValue = EditMultiChoiceQuestionEvent' $ entity {uuid = newValue} setUuid (EditListQuestionEvent' entity) newValue = EditListQuestionEvent' $ entity {uuid = newValue} setUuid (EditValueQuestionEvent' entity) newValue = EditValueQuestionEvent' $ entity {uuid = newValue} setUuid (EditIntegrationQuestionEvent' entity) newValue = EditIntegrationQuestionEvent' $ entity {uuid = newValue} setUuid (EditItemSelectQuestionEvent' entity) newValue = EditItemSelectQuestionEvent' $ entity {uuid = newValue} + setUuid (EditFileQuestionEvent' entity) newValue = EditFileQuestionEvent' $ entity {uuid = newValue} instance HasUuid' DeleteQuestionEvent where getUuid entity = entity.uuid @@ -48,12 +52,14 @@ instance HasParentUuid' AddQuestionEvent where getParentUuid (AddValueQuestionEvent' entity) = entity.parentUuid getParentUuid (AddIntegrationQuestionEvent' entity) = entity.parentUuid getParentUuid (AddItemSelectQuestionEvent' entity) = entity.parentUuid + getParentUuid (AddFileQuestionEvent' entity) = entity.parentUuid setParentUuid (AddOptionsQuestionEvent' entity) newValue = AddOptionsQuestionEvent' $ entity {parentUuid = newValue} setParentUuid (AddMultiChoiceQuestionEvent' entity) newValue = AddMultiChoiceQuestionEvent' $ entity {parentUuid = newValue} setParentUuid (AddListQuestionEvent' entity) newValue = AddListQuestionEvent' $ entity {parentUuid = newValue} setParentUuid (AddValueQuestionEvent' entity) newValue = AddValueQuestionEvent' $ entity {parentUuid = newValue} setParentUuid (AddIntegrationQuestionEvent' entity) newValue = AddIntegrationQuestionEvent' $ entity {parentUuid = newValue} setParentUuid (AddItemSelectQuestionEvent' entity) newValue = AddItemSelectQuestionEvent' $ entity {parentUuid = newValue} + setParentUuid (AddFileQuestionEvent' entity) newValue = AddFileQuestionEvent' $ entity {parentUuid = newValue} instance HasParentUuid' EditQuestionEvent where getParentUuid (EditOptionsQuestionEvent' entity) = entity.parentUuid @@ -62,12 +68,14 @@ instance HasParentUuid' EditQuestionEvent where getParentUuid (EditValueQuestionEvent' entity) = entity.parentUuid getParentUuid (EditIntegrationQuestionEvent' entity) = entity.parentUuid getParentUuid (EditItemSelectQuestionEvent' entity) = entity.parentUuid + getParentUuid (EditFileQuestionEvent' entity) = entity.parentUuid setParentUuid (EditOptionsQuestionEvent' entity) newValue = EditOptionsQuestionEvent' $ entity {parentUuid = newValue} setParentUuid (EditMultiChoiceQuestionEvent' entity) newValue = EditMultiChoiceQuestionEvent' $ entity {parentUuid = newValue} setParentUuid (EditListQuestionEvent' entity) newValue = EditListQuestionEvent' $ entity {parentUuid = newValue} setParentUuid (EditValueQuestionEvent' entity) newValue = EditValueQuestionEvent' $ entity {parentUuid = newValue} setParentUuid (EditIntegrationQuestionEvent' entity) newValue = EditIntegrationQuestionEvent' $ entity {parentUuid = newValue} setParentUuid (EditItemSelectQuestionEvent' entity) newValue = EditItemSelectQuestionEvent' $ entity {parentUuid = newValue} + setParentUuid (EditFileQuestionEvent' entity) newValue = EditFileQuestionEvent' $ entity {parentUuid = newValue} instance HasParentUuid' DeleteQuestionEvent where getParentUuid entity = entity.parentUuid @@ -82,12 +90,14 @@ instance HasEntityUuid' AddQuestionEvent where getEntityUuid (AddValueQuestionEvent' entity) = entity.entityUuid getEntityUuid (AddIntegrationQuestionEvent' entity) = entity.entityUuid getEntityUuid (AddItemSelectQuestionEvent' entity) = entity.entityUuid + getEntityUuid (AddFileQuestionEvent' entity) = entity.entityUuid setEntityUuid (AddOptionsQuestionEvent' entity) newValue = AddOptionsQuestionEvent' $ entity {entityUuid = newValue} setEntityUuid (AddMultiChoiceQuestionEvent' entity) newValue = AddMultiChoiceQuestionEvent' $ entity {entityUuid = newValue} setEntityUuid (AddListQuestionEvent' entity) newValue = AddListQuestionEvent' $ entity {entityUuid = newValue} setEntityUuid (AddValueQuestionEvent' entity) newValue = AddValueQuestionEvent' $ entity {entityUuid = newValue} setEntityUuid (AddIntegrationQuestionEvent' entity) newValue = AddIntegrationQuestionEvent' $ entity {entityUuid = newValue} setEntityUuid (AddItemSelectQuestionEvent' entity) newValue = AddItemSelectQuestionEvent' $ entity {entityUuid = newValue} + setEntityUuid (AddFileQuestionEvent' entity) newValue = AddFileQuestionEvent' $ entity {entityUuid = newValue} instance HasEntityUuid' EditQuestionEvent where getEntityUuid (EditOptionsQuestionEvent' entity) = entity.entityUuid @@ -96,12 +106,14 @@ instance HasEntityUuid' EditQuestionEvent where getEntityUuid (EditValueQuestionEvent' entity) = entity.entityUuid getEntityUuid (EditIntegrationQuestionEvent' entity) = entity.entityUuid getEntityUuid (EditItemSelectQuestionEvent' entity) = entity.entityUuid + getEntityUuid (EditFileQuestionEvent' entity) = entity.entityUuid setEntityUuid (EditOptionsQuestionEvent' entity) newValue = EditOptionsQuestionEvent' $ entity {entityUuid = newValue} setEntityUuid (EditMultiChoiceQuestionEvent' entity) newValue = EditMultiChoiceQuestionEvent' $ entity {entityUuid = newValue} setEntityUuid (EditListQuestionEvent' entity) newValue = EditListQuestionEvent' $ entity {entityUuid = newValue} setEntityUuid (EditValueQuestionEvent' entity) newValue = EditValueQuestionEvent' $ entity {entityUuid = newValue} setEntityUuid (EditIntegrationQuestionEvent' entity) newValue = EditIntegrationQuestionEvent' $ entity {entityUuid = newValue} setEntityUuid (EditItemSelectQuestionEvent' entity) newValue = EditItemSelectQuestionEvent' $ entity {entityUuid = newValue} + setEntityUuid (EditFileQuestionEvent' entity) newValue = EditFileQuestionEvent' $ entity {entityUuid = newValue} instance HasEntityUuid' DeleteQuestionEvent where getEntityUuid entity = entity.entityUuid @@ -116,12 +128,14 @@ instance HasCreatedAt' AddQuestionEvent where getCreatedAt (AddValueQuestionEvent' entity) = entity.createdAt getCreatedAt (AddIntegrationQuestionEvent' entity) = entity.createdAt getCreatedAt (AddItemSelectQuestionEvent' entity) = entity.createdAt + getCreatedAt (AddFileQuestionEvent' entity) = entity.createdAt setCreatedAt (AddOptionsQuestionEvent' entity) newValue = AddOptionsQuestionEvent' $ entity {createdAt = newValue} setCreatedAt (AddMultiChoiceQuestionEvent' entity) newValue = AddMultiChoiceQuestionEvent' $ entity {createdAt = newValue} setCreatedAt (AddListQuestionEvent' entity) newValue = AddListQuestionEvent' $ entity {createdAt = newValue} setCreatedAt (AddValueQuestionEvent' entity) newValue = AddValueQuestionEvent' $ entity {createdAt = newValue} setCreatedAt (AddIntegrationQuestionEvent' entity) newValue = AddIntegrationQuestionEvent' $ entity {createdAt = newValue} setCreatedAt (AddItemSelectQuestionEvent' entity) newValue = AddItemSelectQuestionEvent' $ entity {createdAt = newValue} + setCreatedAt (AddFileQuestionEvent' entity) newValue = AddFileQuestionEvent' $ entity {createdAt = newValue} instance HasCreatedAt' EditQuestionEvent where getCreatedAt (EditOptionsQuestionEvent' entity) = entity.createdAt @@ -130,12 +144,14 @@ instance HasCreatedAt' EditQuestionEvent where getCreatedAt (EditValueQuestionEvent' entity) = entity.createdAt getCreatedAt (EditIntegrationQuestionEvent' entity) = entity.createdAt getCreatedAt (EditItemSelectQuestionEvent' entity) = entity.createdAt + getCreatedAt (EditFileQuestionEvent' entity) = entity.createdAt setCreatedAt (EditOptionsQuestionEvent' entity) newValue = EditOptionsQuestionEvent' $ entity {createdAt = newValue} setCreatedAt (EditMultiChoiceQuestionEvent' entity) newValue = EditMultiChoiceQuestionEvent' $ entity {createdAt = newValue} setCreatedAt (EditListQuestionEvent' entity) newValue = EditListQuestionEvent' $ entity {createdAt = newValue} setCreatedAt (EditValueQuestionEvent' entity) newValue = EditValueQuestionEvent' $ entity {createdAt = newValue} setCreatedAt (EditIntegrationQuestionEvent' entity) newValue = EditIntegrationQuestionEvent' $ entity {createdAt = newValue} setCreatedAt (EditItemSelectQuestionEvent' entity) newValue = EditItemSelectQuestionEvent' $ entity {createdAt = newValue} + setCreatedAt (EditFileQuestionEvent' entity) newValue = EditFileQuestionEvent' $ entity {createdAt = newValue} instance HasCreatedAt' DeleteQuestionEvent where getCreatedAt entity = entity.createdAt @@ -150,12 +166,14 @@ instance HasExpertUuids' EditQuestionEvent (EventField [U.UUID]) where getExpertUuids (EditValueQuestionEvent' entity) = entity.expertUuids getExpertUuids (EditIntegrationQuestionEvent' entity) = entity.expertUuids getExpertUuids (EditItemSelectQuestionEvent' entity) = entity.expertUuids + getExpertUuids (EditFileQuestionEvent' entity) = entity.expertUuids setExpertUuids (EditOptionsQuestionEvent' entity) newValue = EditOptionsQuestionEvent' $ entity {expertUuids = newValue} setExpertUuids (EditMultiChoiceQuestionEvent' entity) newValue = EditMultiChoiceQuestionEvent' $ entity {expertUuids = newValue} setExpertUuids (EditListQuestionEvent' entity) newValue = EditListQuestionEvent' $ entity {expertUuids = newValue} setExpertUuids (EditValueQuestionEvent' entity) newValue = EditValueQuestionEvent' $ entity {expertUuids = newValue} setExpertUuids (EditIntegrationQuestionEvent' entity) newValue = EditIntegrationQuestionEvent' $ entity {expertUuids = newValue} setExpertUuids (EditItemSelectQuestionEvent' entity) newValue = EditItemSelectQuestionEvent' $ entity {expertUuids = newValue} + setExpertUuids (EditFileQuestionEvent' entity) newValue = EditFileQuestionEvent' $ entity {expertUuids = newValue} ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ @@ -166,9 +184,11 @@ instance HasReferenceUuids' EditQuestionEvent (EventField [U.UUID]) where getReferenceUuids (EditValueQuestionEvent' entity) = entity.referenceUuids getReferenceUuids (EditIntegrationQuestionEvent' entity) = entity.referenceUuids getReferenceUuids (EditItemSelectQuestionEvent' entity) = entity.referenceUuids + getReferenceUuids (EditFileQuestionEvent' entity) = entity.referenceUuids setReferenceUuids (EditOptionsQuestionEvent' entity) newValue = EditOptionsQuestionEvent' $ entity {referenceUuids = newValue} setReferenceUuids (EditMultiChoiceQuestionEvent' entity) newValue = EditMultiChoiceQuestionEvent' $ entity {referenceUuids = newValue} setReferenceUuids (EditListQuestionEvent' entity) newValue = EditListQuestionEvent' $ entity {referenceUuids = newValue} setReferenceUuids (EditValueQuestionEvent' entity) newValue = EditValueQuestionEvent' $ entity {referenceUuids = newValue} setReferenceUuids (EditIntegrationQuestionEvent' entity) newValue = EditIntegrationQuestionEvent' $ entity {referenceUuids = newValue} setReferenceUuids (EditItemSelectQuestionEvent' entity) newValue = EditItemSelectQuestionEvent' $ entity {referenceUuids = newValue} + setReferenceUuids (EditFileQuestionEvent' entity) newValue = EditFileQuestionEvent' $ entity {referenceUuids = newValue} diff --git a/wizard-common/src/WizardLib/KnowledgeModel/Model/Event/Question/QuestionEventUtil.hs b/wizard-common/src/WizardLib/KnowledgeModel/Model/Event/Question/QuestionEventUtil.hs index e7c73721b..5027e9321 100644 --- a/wizard-common/src/WizardLib/KnowledgeModel/Model/Event/Question/QuestionEventUtil.hs +++ b/wizard-common/src/WizardLib/KnowledgeModel/Model/Event/Question/QuestionEventUtil.hs @@ -69,3 +69,30 @@ instance IsEmptyEvent EditIntegrationQuestionEvent where , isChangedValue event.integrationUuid , isChangedValue event.props ] + +instance IsEmptyEvent EditItemSelectQuestionEvent where + isEmptyEvent event = + or + [ isChangedValue event.title + , isChangedValue event.text + , isChangedValue event.requiredPhaseUuid + , isChangedValue event.annotations + , isChangedValue event.tagUuids + , isChangedValue event.expertUuids + , isChangedValue event.referenceUuids + , isChangedValue event.listQuestionUuid + ] + +instance IsEmptyEvent EditFileQuestionEvent where + isEmptyEvent event = + or + [ isChangedValue event.title + , isChangedValue event.text + , isChangedValue event.requiredPhaseUuid + , isChangedValue event.annotations + , isChangedValue event.tagUuids + , isChangedValue event.expertUuids + , isChangedValue event.referenceUuids + , isChangedValue event.maxSize + , isChangedValue event.fileTypes + ] diff --git a/wizard-common/src/WizardLib/KnowledgeModel/Model/KnowledgeModel/KnowledgeModel.hs b/wizard-common/src/WizardLib/KnowledgeModel/Model/KnowledgeModel/KnowledgeModel.hs index ca863e3bb..bf90da6b4 100644 --- a/wizard-common/src/WizardLib/KnowledgeModel/Model/KnowledgeModel/KnowledgeModel.hs +++ b/wizard-common/src/WizardLib/KnowledgeModel/Model/KnowledgeModel/KnowledgeModel.hs @@ -68,6 +68,7 @@ data Question | ValueQuestion' ValueQuestion | IntegrationQuestion' IntegrationQuestion | ItemSelectQuestion' ItemSelectQuestion + | FileQuestion' FileQuestion deriving (Show, Eq, Generic) data OptionsQuestion = OptionsQuestion @@ -149,6 +150,20 @@ data ItemSelectQuestion = ItemSelectQuestion } deriving (Show, Eq, Generic) +data FileQuestion = FileQuestion + { uuid :: U.UUID + , title :: String + , text :: Maybe String + , requiredPhaseUuid :: Maybe U.UUID + , annotations :: [MapEntry String String] + , tagUuids :: [U.UUID] + , expertUuids :: [U.UUID] + , referenceUuids :: [U.UUID] + , maxSize :: Maybe Int + , fileTypes :: Maybe String + } + deriving (Show, Eq, Generic) + -- ------------------------------------------------ data Answer = Answer { uuid :: U.UUID diff --git a/wizard-common/src/WizardLib/KnowledgeModel/Model/KnowledgeModel/KnowledgeModelLenses.hs b/wizard-common/src/WizardLib/KnowledgeModel/Model/KnowledgeModel/KnowledgeModelLenses.hs index 5020ce5d9..ea920dac5 100644 --- a/wizard-common/src/WizardLib/KnowledgeModel/Model/KnowledgeModel/KnowledgeModelLenses.hs +++ b/wizard-common/src/WizardLib/KnowledgeModel/Model/KnowledgeModel/KnowledgeModelLenses.hs @@ -142,12 +142,14 @@ instance HasUuid' Question where getUuid (ValueQuestion' entity) = entity.uuid getUuid (IntegrationQuestion' entity) = entity.uuid getUuid (ItemSelectQuestion' entity) = entity.uuid + getUuid (FileQuestion' entity) = entity.uuid setUuid (OptionsQuestion' entity) newValue = OptionsQuestion' $ entity {uuid = newValue} setUuid (MultiChoiceQuestion' entity) newValue = MultiChoiceQuestion' $ entity {uuid = newValue} setUuid (ListQuestion' entity) newValue = ListQuestion' $ entity {uuid = newValue} setUuid (ValueQuestion' entity) newValue = ValueQuestion' $ entity {uuid = newValue} setUuid (IntegrationQuestion' entity) newValue = IntegrationQuestion' $ entity {uuid = newValue} setUuid (ItemSelectQuestion' entity) newValue = ItemSelectQuestion' $ entity {uuid = newValue} + setUuid (FileQuestion' entity) newValue = FileQuestion' $ entity {uuid = newValue} instance HasUuid' Expert where getUuid entity = entity.uuid @@ -211,12 +213,14 @@ instance HasAnnotations' Question where getAnnotations (ValueQuestion' entity) = entity.annotations getAnnotations (IntegrationQuestion' entity) = entity.annotations getAnnotations (ItemSelectQuestion' entity) = entity.annotations + getAnnotations (FileQuestion' entity) = entity.annotations setAnnotations (OptionsQuestion' entity) newValue = OptionsQuestion' $ entity {annotations = newValue} setAnnotations (MultiChoiceQuestion' entity) newValue = MultiChoiceQuestion' $ entity {annotations = newValue} setAnnotations (ListQuestion' entity) newValue = ListQuestion' $ entity {annotations = newValue} setAnnotations (ValueQuestion' entity) newValue = ValueQuestion' $ entity {annotations = newValue} setAnnotations (IntegrationQuestion' entity) newValue = IntegrationQuestion' $ entity {annotations = newValue} setAnnotations (ItemSelectQuestion' entity) newValue = ItemSelectQuestion' $ entity {annotations = newValue} + setAnnotations (FileQuestion' entity) newValue = FileQuestion' $ entity {annotations = newValue} instance HasAnnotations' Expert where getAnnotations entity = entity.annotations @@ -264,12 +268,14 @@ instance HasTitle' Question where getTitle (ValueQuestion' q) = q.title getTitle (IntegrationQuestion' q) = q.title getTitle (ItemSelectQuestion' q) = q.title + getTitle (FileQuestion' q) = q.title setTitle (OptionsQuestion' q) newValue = OptionsQuestion' $ q {title = newValue} setTitle (MultiChoiceQuestion' q) newValue = MultiChoiceQuestion' $ q {title = newValue} setTitle (ListQuestion' q) newValue = ListQuestion' $ q {title = newValue} setTitle (ValueQuestion' q) newValue = ValueQuestion' $ q {title = newValue} setTitle (IntegrationQuestion' q) newValue = IntegrationQuestion' $ q {title = newValue} setTitle (ItemSelectQuestion' q) newValue = ItemSelectQuestion' $ q {title = newValue} + setTitle (FileQuestion' q) newValue = FileQuestion' $ q {title = newValue} ------------------------------------------------------------------------------------------ instance HasText' Question where @@ -279,12 +285,14 @@ instance HasText' Question where getText (ValueQuestion' q) = q.text getText (IntegrationQuestion' q) = q.text getText (ItemSelectQuestion' q) = q.text + getText (FileQuestion' q) = q.text setText (OptionsQuestion' q) newValue = OptionsQuestion' $ q {text = newValue} setText (MultiChoiceQuestion' q) newValue = MultiChoiceQuestion' $ q {text = newValue} setText (ListQuestion' q) newValue = ListQuestion' $ q {text = newValue} setText (ValueQuestion' q) newValue = ValueQuestion' $ q {text = newValue} setText (IntegrationQuestion' q) newValue = IntegrationQuestion' $ q {text = newValue} setText (ItemSelectQuestion' q) newValue = ItemSelectQuestion' $ q {text = newValue} + setText (FileQuestion' q) newValue = FileQuestion' $ q {text = newValue} ------------------------------------------------------------------------------------------ instance HasRequiredPhaseUuid' Question where @@ -294,12 +302,14 @@ instance HasRequiredPhaseUuid' Question where getRequiredPhaseUuid (ValueQuestion' q) = q.requiredPhaseUuid getRequiredPhaseUuid (IntegrationQuestion' q) = q.requiredPhaseUuid getRequiredPhaseUuid (ItemSelectQuestion' q) = q.requiredPhaseUuid + getRequiredPhaseUuid (FileQuestion' q) = q.requiredPhaseUuid setRequiredPhaseUuid (OptionsQuestion' q) newValue = OptionsQuestion' $ q {requiredPhaseUuid = newValue} setRequiredPhaseUuid (MultiChoiceQuestion' q) newValue = MultiChoiceQuestion' $ q {requiredPhaseUuid = newValue} setRequiredPhaseUuid (ListQuestion' q) newValue = ListQuestion' $ q {requiredPhaseUuid = newValue} setRequiredPhaseUuid (ValueQuestion' q) newValue = ValueQuestion' $ q {requiredPhaseUuid = newValue} setRequiredPhaseUuid (IntegrationQuestion' q) newValue = IntegrationQuestion' $ q {requiredPhaseUuid = newValue} setRequiredPhaseUuid (ItemSelectQuestion' q) newValue = ItemSelectQuestion' $ q {requiredPhaseUuid = newValue} + setRequiredPhaseUuid (FileQuestion' q) newValue = FileQuestion' $ q {requiredPhaseUuid = newValue} ------------------------------------------------------------------------------------------ instance HasTagUuids' Question where @@ -309,12 +319,14 @@ instance HasTagUuids' Question where getTagUuids (ValueQuestion' q) = q.tagUuids getTagUuids (IntegrationQuestion' q) = q.tagUuids getTagUuids (ItemSelectQuestion' q) = q.tagUuids + getTagUuids (FileQuestion' q) = q.tagUuids setTagUuids (OptionsQuestion' q) newValue = OptionsQuestion' $ q {tagUuids = newValue} setTagUuids (MultiChoiceQuestion' q) newValue = MultiChoiceQuestion' $ q {tagUuids = newValue} setTagUuids (ListQuestion' q) newValue = ListQuestion' $ q {tagUuids = newValue} setTagUuids (ValueQuestion' q) newValue = ValueQuestion' $ q {tagUuids = newValue} setTagUuids (IntegrationQuestion' q) newValue = IntegrationQuestion' $ q {tagUuids = newValue} setTagUuids (ItemSelectQuestion' q) newValue = ItemSelectQuestion' $ q {tagUuids = newValue} + setTagUuids (FileQuestion' q) newValue = FileQuestion' $ q {tagUuids = newValue} -- ------------------------------------------------------------------------------------------ instance HasExpertUuids' Question [U.UUID] where @@ -324,12 +336,13 @@ instance HasExpertUuids' Question [U.UUID] where getExpertUuids (ValueQuestion' entity) = entity.expertUuids getExpertUuids (IntegrationQuestion' entity) = entity.expertUuids getExpertUuids (ItemSelectQuestion' entity) = entity.expertUuids + getExpertUuids (FileQuestion' entity) = entity.expertUuids setExpertUuids (OptionsQuestion' entity) newValue = OptionsQuestion' $ entity {expertUuids = newValue} setExpertUuids (MultiChoiceQuestion' entity) newValue = MultiChoiceQuestion' $ entity {expertUuids = newValue} setExpertUuids (ListQuestion' entity) newValue = ListQuestion' $ entity {expertUuids = newValue} setExpertUuids (ValueQuestion' entity) newValue = ValueQuestion' $ entity {expertUuids = newValue} setExpertUuids (IntegrationQuestion' entity) newValue = IntegrationQuestion' $ entity {expertUuids = newValue} - setExpertUuids (ItemSelectQuestion' entity) newValue = ItemSelectQuestion' $ entity {expertUuids = newValue} + setExpertUuids (FileQuestion' entity) newValue = FileQuestion' $ entity {expertUuids = newValue} -- ------------------------------------------------------------------------------------------ instance HasReferenceUuids' Question [U.UUID] where @@ -339,12 +352,14 @@ instance HasReferenceUuids' Question [U.UUID] where getReferenceUuids (ValueQuestion' q) = q.referenceUuids getReferenceUuids (IntegrationQuestion' q) = q.referenceUuids getReferenceUuids (ItemSelectQuestion' q) = q.referenceUuids + getReferenceUuids (FileQuestion' q) = q.referenceUuids setReferenceUuids (OptionsQuestion' q) newValue = OptionsQuestion' $ q {referenceUuids = newValue} setReferenceUuids (MultiChoiceQuestion' q) newValue = MultiChoiceQuestion' $ q {referenceUuids = newValue} setReferenceUuids (ListQuestion' q) newValue = ListQuestion' $ q {referenceUuids = newValue} setReferenceUuids (ValueQuestion' q) newValue = ValueQuestion' $ q {referenceUuids = newValue} setReferenceUuids (IntegrationQuestion' q) newValue = IntegrationQuestion' $ q {referenceUuids = newValue} setReferenceUuids (ItemSelectQuestion' q) newValue = ItemSelectQuestion' $ q {referenceUuids = newValue} + setReferenceUuids (FileQuestion' q) newValue = FileQuestion' $ q {referenceUuids = newValue} -- ------------------------------------------------------------------------------------------ instance HasAnswerUuids' Question where diff --git a/wizard-server/src/Wizard/Api/Handler/Api.hs b/wizard-server/src/Wizard/Api/Handler/Api.hs index c5d0192a4..8f00d56d9 100644 --- a/wizard-server/src/Wizard/Api/Handler/Api.hs +++ b/wizard-server/src/Wizard/Api/Handler/Api.hs @@ -28,6 +28,7 @@ import Wizard.Api.Handler.Questionnaire.Api import Wizard.Api.Handler.Questionnaire.Event.Api import Wizard.Api.Handler.Questionnaire.Version.Api import Wizard.Api.Handler.QuestionnaireAction.Api +import Wizard.Api.Handler.QuestionnaireFile.Api import Wizard.Api.Handler.QuestionnaireImporter.Api import Wizard.Api.Handler.Registry.Api import Wizard.Api.Handler.Submission.Api @@ -65,6 +66,7 @@ type ApplicationAPI = :<|> QuestionnaireAPI :<|> QuestionnaireEventAPI :<|> QuestionnaireVersionAPI + :<|> QuestionnaireFileAPI :<|> QuestionnaireActionAPI :<|> QuestionnaireImporterAPI :<|> RegistryAPI @@ -106,6 +108,7 @@ applicationServer = :<|> questionnaireServer :<|> questionnaireEventServer :<|> questionnaireVersionServer + :<|> questionnaireFileServer :<|> questionnaireActionServer :<|> questionnaireImporterServer :<|> registryServer diff --git a/wizard-server/src/Wizard/Api/Handler/Questionnaire/Api.hs b/wizard-server/src/Wizard/Api/Handler/Questionnaire/Api.hs index 104231b5b..3967f8625 100644 --- a/wizard-server/src/Wizard/Api/Handler/Questionnaire/Api.hs +++ b/wizard-server/src/Wizard/Api/Handler/Questionnaire/Api.hs @@ -18,6 +18,7 @@ import Wizard.Api.Handler.Questionnaire.Detail_Settings_GET import Wizard.Api.Handler.Questionnaire.Detail_Settings_PUT import Wizard.Api.Handler.Questionnaire.Detail_Share_PUT import Wizard.Api.Handler.Questionnaire.Detail_WS +import Wizard.Api.Handler.Questionnaire.File.Api import Wizard.Api.Handler.Questionnaire.List_GET import Wizard.Api.Handler.Questionnaire.List_POST import Wizard.Api.Handler.Questionnaire.List_POST_CloneUuid @@ -48,6 +49,7 @@ type QuestionnaireAPI = :<|> Detail_Revert_Preview_POST :<|> List_Suggestions_GET :<|> QuestionnaireCommentAPI + :<|> QuestionnaireFileAPI :<|> QuestionnaireUserAPI ) @@ -76,4 +78,5 @@ questionnaireServer = :<|> detail_revert_preview_POST :<|> list_suggestions_GET :<|> questionnaireCommentServer + :<|> questionnaireFileServer :<|> questionnaireUserServer diff --git a/wizard-server/src/Wizard/Api/Handler/Questionnaire/File/Api.hs b/wizard-server/src/Wizard/Api/Handler/Questionnaire/File/Api.hs new file mode 100644 index 000000000..3ad0720ad --- /dev/null +++ b/wizard-server/src/Wizard/Api/Handler/Questionnaire/File/Api.hs @@ -0,0 +1,28 @@ +module Wizard.Api.Handler.Questionnaire.File.Api where + +import Servant +import Servant.Swagger.Tags + +import Wizard.Api.Handler.Questionnaire.File.Detail_DELETE +import Wizard.Api.Handler.Questionnaire.File.Detail_Download_GET +import Wizard.Api.Handler.Questionnaire.File.List_GET +import Wizard.Api.Handler.Questionnaire.File.List_POST +import Wizard.Model.Context.BaseContext + +type QuestionnaireFileAPI = + Tags "Questionnaire File" + :> ( List_GET + :<|> List_POST + :<|> Detail_DELETE + :<|> Detail_Download_GET + ) + +questionnaireFileApi :: Proxy QuestionnaireFileAPI +questionnaireFileApi = Proxy + +questionnaireFileServer :: ServerT QuestionnaireFileAPI BaseContextM +questionnaireFileServer = + list_GET + :<|> list_POST + :<|> detail_DELETE + :<|> detail_download_GET diff --git a/wizard-server/src/Wizard/Api/Handler/Questionnaire/File/Detail_DELETE.hs b/wizard-server/src/Wizard/Api/Handler/Questionnaire/File/Detail_DELETE.hs new file mode 100644 index 000000000..1efcbafaa --- /dev/null +++ b/wizard-server/src/Wizard/Api/Handler/Questionnaire/File/Detail_DELETE.hs @@ -0,0 +1,27 @@ +module Wizard.Api.Handler.Questionnaire.File.Detail_DELETE where + +import qualified Data.UUID as U +import Servant + +import Shared.Common.Api.Handler.Common +import Shared.Common.Model.Context.TransactionState +import Wizard.Api.Handler.Common +import Wizard.Model.Context.BaseContext +import Wizard.Service.Questionnaire.File.QuestionnaireFileService + +type Detail_DELETE = + Header "Authorization" String + :> Header "Host" String + :> "questionnaires" + :> Capture "questionnaireUuid" U.UUID + :> "files" + :> Capture "fileUuid" U.UUID + :> Verb DELETE 204 '[SafeJSON] (Headers '[Header "x-trace-uuid" String] NoContent) + +detail_DELETE :: Maybe String -> Maybe String -> U.UUID -> U.UUID -> BaseContextM (Headers '[Header "x-trace-uuid" String] NoContent) +detail_DELETE mTokenHeader mServerUrl qtnUuid fileUuid = + getMaybeAuthServiceExecutor mTokenHeader mServerUrl $ \runInAuthService -> + runInAuthService Transactional $ + addTraceUuidHeader =<< do + deleteQuestionnaireFile qtnUuid fileUuid + return NoContent diff --git a/wizard-server/src/Wizard/Api/Handler/Questionnaire/File/Detail_Download_GET.hs b/wizard-server/src/Wizard/Api/Handler/Questionnaire/File/Detail_Download_GET.hs new file mode 100644 index 000000000..8fc16234d --- /dev/null +++ b/wizard-server/src/Wizard/Api/Handler/Questionnaire/File/Detail_Download_GET.hs @@ -0,0 +1,26 @@ +module Wizard.Api.Handler.Questionnaire.File.Detail_Download_GET where + +import qualified Data.UUID as U +import Servant + +import Shared.Common.Api.Handler.Common +import Shared.Common.Model.Context.TransactionState +import Wizard.Api.Handler.Common +import Wizard.Api.Resource.TemporaryFile.TemporaryFileDTO +import Wizard.Api.Resource.TemporaryFile.TemporaryFileJM () +import Wizard.Model.Context.BaseContext +import Wizard.Service.Questionnaire.File.QuestionnaireFileService + +type Detail_Download_GET = + Header "Authorization" String + :> Header "Host" String + :> "questionnaires" + :> Capture "questionnaireUuid" U.UUID + :> "files" + :> Capture "fileUuid" U.UUID + :> Get '[SafeJSON] (Headers '[Header "x-trace-uuid" String] TemporaryFileDTO) + +detail_download_GET :: Maybe String -> Maybe String -> U.UUID -> U.UUID -> BaseContextM (Headers '[Header "x-trace-uuid" String] TemporaryFileDTO) +detail_download_GET mTokenHeader mServerUrl qtnUuid fileUuid = + getMaybeAuthServiceExecutor mTokenHeader mServerUrl $ \runInMaybeAuthService -> + runInMaybeAuthService Transactional $ addTraceUuidHeader =<< downloadQuestionnaireFile qtnUuid fileUuid diff --git a/wizard-server/src/Wizard/Api/Handler/Questionnaire/File/List_GET.hs b/wizard-server/src/Wizard/Api/Handler/Questionnaire/File/List_GET.hs new file mode 100644 index 000000000..86243b326 --- /dev/null +++ b/wizard-server/src/Wizard/Api/Handler/Questionnaire/File/List_GET.hs @@ -0,0 +1,40 @@ +module Wizard.Api.Handler.Questionnaire.File.List_GET where + +import qualified Data.UUID as U +import Servant + +import Shared.Common.Api.Handler.Common +import Shared.Common.Model.Common.Page +import Shared.Common.Model.Common.Pageable +import Shared.Common.Model.Context.TransactionState +import Wizard.Api.Handler.Common +import Wizard.Api.Resource.Questionnaire.File.QuestionnaireFileListJM () +import Wizard.Model.Context.BaseContext +import Wizard.Model.Questionnaire.QuestionnaireFileList +import Wizard.Service.Questionnaire.File.QuestionnaireFileService + +type List_GET = + Header "Authorization" String + :> Header "Host" String + :> "questionnaires" + :> Capture "questionnaireUuid" U.UUID + :> "files" + :> QueryParam "q" String + :> QueryParam "page" Int + :> QueryParam "size" Int + :> QueryParam "sort" String + :> Get '[SafeJSON] (Headers '[Header "x-trace-uuid" String] (Page QuestionnaireFileList)) + +list_GET + :: Maybe String + -> Maybe String + -> U.UUID + -> Maybe String + -> Maybe Int + -> Maybe Int + -> Maybe String + -> BaseContextM (Headers '[Header "x-trace-uuid" String] (Page QuestionnaireFileList)) +list_GET mTokenHeader mServerUrl qtnUuid mQuery mPage mSize mSort = + getAuthServiceExecutor mTokenHeader mServerUrl $ \runInAuthService -> + runInAuthService NoTransaction $ + addTraceUuidHeader =<< getQuestionnaireFilesPage mQuery (Just qtnUuid) (Pageable mPage mSize) (parseSortQuery mSort) diff --git a/wizard-server/src/Wizard/Api/Handler/Questionnaire/File/List_POST.hs b/wizard-server/src/Wizard/Api/Handler/Questionnaire/File/List_POST.hs new file mode 100644 index 000000000..8a363cf96 --- /dev/null +++ b/wizard-server/src/Wizard/Api/Handler/Questionnaire/File/List_POST.hs @@ -0,0 +1,31 @@ +module Wizard.Api.Handler.Questionnaire.File.List_POST where + +import qualified Data.UUID as U +import Servant +import Servant.Multipart + +import Shared.Common.Api.Handler.Common +import Shared.Common.Model.Context.TransactionState +import Wizard.Api.Handler.Common +import Wizard.Api.Resource.File.FileCreateDTO +import Wizard.Api.Resource.File.FileCreateJM () +import Wizard.Api.Resource.Questionnaire.File.QuestionnaireFileListJM () +import Wizard.Model.Context.BaseContext +import Wizard.Model.Questionnaire.QuestionnaireFileList +import Wizard.Service.Questionnaire.File.QuestionnaireFileService + +type List_POST = + Header "Authorization" String + :> Header "Host" String + :> MultipartForm Mem FileCreateDTO + :> "questionnaires" + :> Capture "uuid" U.UUID + :> "files" + :> Verb 'POST 201 '[SafeJSON] (Headers '[Header "x-trace-uuid" String] QuestionnaireFileList) + +list_POST :: Maybe String -> Maybe String -> FileCreateDTO -> U.UUID -> BaseContextM (Headers '[Header "x-trace-uuid" String] QuestionnaireFileList) +list_POST mTokenHeader mServerUrl reqDto qtnUuid = + getMaybeAuthServiceExecutor mTokenHeader mServerUrl $ \runInAuthService -> + runInAuthService Transactional $ + addTraceUuidHeader =<< do + createQuestionnaireFile qtnUuid reqDto diff --git a/wizard-server/src/Wizard/Api/Handler/QuestionnaireFile/Api.hs b/wizard-server/src/Wizard/Api/Handler/QuestionnaireFile/Api.hs new file mode 100644 index 000000000..1cfca6163 --- /dev/null +++ b/wizard-server/src/Wizard/Api/Handler/QuestionnaireFile/Api.hs @@ -0,0 +1,18 @@ +module Wizard.Api.Handler.QuestionnaireFile.Api where + +import Servant +import Servant.Swagger.Tags + +import Wizard.Api.Handler.QuestionnaireFile.List_GET +import Wizard.Model.Context.BaseContext + +type QuestionnaireFileAPI = + Tags "Questionnaire File" + :> List_GET + +questionnaireFileApi :: Proxy QuestionnaireFileAPI +questionnaireFileApi = Proxy + +questionnaireFileServer :: ServerT QuestionnaireFileAPI BaseContextM +questionnaireFileServer = + list_GET diff --git a/wizard-server/src/Wizard/Api/Handler/QuestionnaireFile/List_GET.hs b/wizard-server/src/Wizard/Api/Handler/QuestionnaireFile/List_GET.hs new file mode 100644 index 000000000..3931691e5 --- /dev/null +++ b/wizard-server/src/Wizard/Api/Handler/QuestionnaireFile/List_GET.hs @@ -0,0 +1,36 @@ +module Wizard.Api.Handler.QuestionnaireFile.List_GET where + +import Servant + +import Shared.Common.Api.Handler.Common +import Shared.Common.Model.Common.Page +import Shared.Common.Model.Common.Pageable +import Shared.Common.Model.Context.TransactionState +import Wizard.Api.Handler.Common +import Wizard.Api.Resource.Questionnaire.File.QuestionnaireFileListJM () +import Wizard.Model.Context.BaseContext +import Wizard.Model.Questionnaire.QuestionnaireFileList +import Wizard.Service.Questionnaire.File.QuestionnaireFileService + +type List_GET = + Header "Authorization" String + :> Header "Host" String + :> "questionnaire-files" + :> QueryParam "q" String + :> QueryParam "page" Int + :> QueryParam "size" Int + :> QueryParam "sort" String + :> Get '[SafeJSON] (Headers '[Header "x-trace-uuid" String] (Page QuestionnaireFileList)) + +list_GET + :: Maybe String + -> Maybe String + -> Maybe String + -> Maybe Int + -> Maybe Int + -> Maybe String + -> BaseContextM (Headers '[Header "x-trace-uuid" String] (Page QuestionnaireFileList)) +list_GET mTokenHeader mServerUrl mQuery mPage mSize mSort = + getAuthServiceExecutor mTokenHeader mServerUrl $ \runInAuthService -> + runInAuthService NoTransaction $ + addTraceUuidHeader =<< getQuestionnaireFilesPage mQuery Nothing (Pageable mPage mSize) (parseSortQuery mSort) diff --git a/wizard-server/src/Wizard/Api/Handler/Swagger/Api.hs b/wizard-server/src/Wizard/Api/Handler/Swagger/Api.hs index 721502c80..6aeb1ca31 100644 --- a/wizard-server/src/Wizard/Api/Handler/Swagger/Api.hs +++ b/wizard-server/src/Wizard/Api/Handler/Swagger/Api.hs @@ -46,6 +46,7 @@ import Wizard.Api.Resource.DocumentTemplate.File.DocumentTemplateFileChangeSM () import Wizard.Api.Resource.DocumentTemplate.File.DocumentTemplateFileListSM () import Wizard.Api.Resource.Feedback.FeedbackCreateSM () import Wizard.Api.Resource.Feedback.FeedbackSM () +import Wizard.Api.Resource.File.FileCreateSM () import Wizard.Api.Resource.Locale.LocaleChangeSM () import Wizard.Api.Resource.Locale.LocaleCreateSM () import Wizard.Api.Resource.Locale.LocaleDetailSM () diff --git a/wizard-server/src/Wizard/Api/Resource/Common/PageSM.hs b/wizard-server/src/Wizard/Api/Resource/Common/PageSM.hs index c2f7d2cd6..5ef5ff2cb 100644 --- a/wizard-server/src/Wizard/Api/Resource/Common/PageSM.hs +++ b/wizard-server/src/Wizard/Api/Resource/Common/PageSM.hs @@ -19,6 +19,7 @@ import Wizard.Api.Resource.Package.PackageSimpleDTO import Wizard.Api.Resource.Package.PackageSimpleSM () import Wizard.Api.Resource.Package.PackageSuggestionSM () import Wizard.Api.Resource.PersistentCommand.PersistentCommandSM () +import Wizard.Api.Resource.Questionnaire.File.QuestionnaireFileListSM () import Wizard.Api.Resource.Questionnaire.QuestionnaireCommentThreadAssignedSM () import Wizard.Api.Resource.Questionnaire.QuestionnaireDTO import Wizard.Api.Resource.Questionnaire.QuestionnaireSM () @@ -37,6 +38,7 @@ import Wizard.Database.Migration.Development.Document.Data.Documents import Wizard.Database.Migration.Development.DocumentTemplate.Data.DocumentTemplates import Wizard.Database.Migration.Development.Locale.Data.Locales import Wizard.Database.Migration.Development.Questionnaire.Data.QuestionnaireComments +import Wizard.Database.Migration.Development.Questionnaire.Data.QuestionnaireFiles import Wizard.Database.Migration.Development.Questionnaire.Data.Questionnaires import Wizard.Database.Migration.Development.QuestionnaireAction.Data.QuestionnaireActions import Wizard.Database.Migration.Development.QuestionnaireImporter.Data.QuestionnaireImporters @@ -46,6 +48,7 @@ import Wizard.Model.Branch.BranchList import Wizard.Model.DocumentTemplate.DocumentTemplateDraftList import Wizard.Model.Package.PackageSuggestion import Wizard.Model.Questionnaire.QuestionnaireCommentThreadAssigned +import Wizard.Model.Questionnaire.QuestionnaireFileList import Wizard.Model.Questionnaire.QuestionnaireSuggestion import Wizard.Model.User.UserGroupSuggestion import Wizard.Service.DocumentTemplate.Draft.DocumentTemplateDraftMapper @@ -122,6 +125,12 @@ instance ToSchema (Page QuestionnaireActionDTO) where "Page QuestionnaireActionDTO" (Page "questionnaireActions" pageMetadata [questionnaireActionFtp3Dto]) +instance ToSchema (Page QuestionnaireFileList) where + declareNamedSchema = + toSwaggerWithDtoName + "Page QuestionnaireFileList" + (Page "questionnaireFiles" pageMetadata [questionnaireFileList]) + instance ToSchema (Page QuestionnaireImporterDTO) where declareNamedSchema = toSwaggerWithDtoName diff --git a/wizard-server/src/Wizard/Api/Resource/File/FileCreateDTO.hs b/wizard-server/src/Wizard/Api/Resource/File/FileCreateDTO.hs new file mode 100644 index 000000000..9a93f43c5 --- /dev/null +++ b/wizard-server/src/Wizard/Api/Resource/File/FileCreateDTO.hs @@ -0,0 +1,9 @@ +module Wizard.Api.Resource.File.FileCreateDTO where + +import qualified Data.ByteString.Char8 as BS + +data FileCreateDTO = FileCreateDTO + { fileName :: String + , contentType :: String + , content :: BS.ByteString + } diff --git a/wizard-server/src/Wizard/Api/Resource/File/FileCreateJM.hs b/wizard-server/src/Wizard/Api/Resource/File/FileCreateJM.hs new file mode 100644 index 000000000..b8b116a43 --- /dev/null +++ b/wizard-server/src/Wizard/Api/Resource/File/FileCreateJM.hs @@ -0,0 +1,14 @@ +module Wizard.Api.Resource.File.FileCreateJM where + +import qualified Data.ByteString.Lazy.Char8 as BSL +import qualified Data.Text as T +import Servant.Multipart + +import Wizard.Api.Resource.File.FileCreateDTO + +instance FromMultipart Mem FileCreateDTO where + fromMultipart form = + FileCreateDTO + <$> fmap T.unpack (lookupInput "fileName" form) + <*> fmap (T.unpack . fdFileCType) (lookupFile "file" form) + <*> fmap (BSL.toStrict . fdPayload) (lookupFile "file" form) diff --git a/wizard-server/src/Wizard/Api/Resource/File/FileCreateSM.hs b/wizard-server/src/Wizard/Api/Resource/File/FileCreateSM.hs new file mode 100644 index 000000000..c5e3eef7d --- /dev/null +++ b/wizard-server/src/Wizard/Api/Resource/File/FileCreateSM.hs @@ -0,0 +1,38 @@ +module Wizard.Api.Resource.File.FileCreateSM where + +import Data.Swagger +import Servant +import Servant.Multipart +import Servant.Swagger +import Servant.Swagger.Internal + +import Wizard.Api.Resource.File.FileCreateDTO + +instance HasSwagger api => HasSwagger (MultipartForm Mem FileCreateDTO :> api) where + toSwagger _ = addParam fileNameField . addParam fileField $ toSwagger (Proxy :: Proxy api) + where + fileNameField = + Param + { _paramName = "fileName" + , _paramDescription = Just "FileName" + , _paramRequired = Just True + , _paramSchema = + ParamOther + ( mempty + { _paramOtherSchemaIn = ParamFormData + } + ) + } + fileField = + Param + { _paramName = "file" + , _paramDescription = Just "File to upload" + , _paramRequired = Just True + , _paramSchema = + ParamOther + ( mempty + { _paramOtherSchemaIn = ParamFormData + , _paramOtherSchemaParamSchema = mempty {_paramSchemaType = Just SwaggerFile} + } + ) + } diff --git a/wizard-server/src/Wizard/Api/Resource/Questionnaire/File/QuestionnaireFileListJM.hs b/wizard-server/src/Wizard/Api/Resource/Questionnaire/File/QuestionnaireFileListJM.hs new file mode 100644 index 000000000..151214d36 --- /dev/null +++ b/wizard-server/src/Wizard/Api/Resource/Questionnaire/File/QuestionnaireFileListJM.hs @@ -0,0 +1,14 @@ +module Wizard.Api.Resource.Questionnaire.File.QuestionnaireFileListJM where + +import Data.Aeson + +import Shared.Common.Util.Aeson +import Wizard.Api.Resource.Questionnaire.QuestionnaireSimpleJM () +import Wizard.Model.Questionnaire.QuestionnaireFileList +import WizardLib.Public.Api.Resource.User.UserSuggestionJM () + +instance FromJSON QuestionnaireFileList where + parseJSON = genericParseJSON jsonOptions + +instance ToJSON QuestionnaireFileList where + toJSON = genericToJSON jsonOptions diff --git a/wizard-server/src/Wizard/Api/Resource/Questionnaire/File/QuestionnaireFileListSM.hs b/wizard-server/src/Wizard/Api/Resource/Questionnaire/File/QuestionnaireFileListSM.hs new file mode 100644 index 000000000..64604a868 --- /dev/null +++ b/wizard-server/src/Wizard/Api/Resource/Questionnaire/File/QuestionnaireFileListSM.hs @@ -0,0 +1,13 @@ +module Wizard.Api.Resource.Questionnaire.File.QuestionnaireFileListSM where + +import Data.Swagger + +import Shared.Common.Util.Swagger +import Wizard.Api.Resource.Questionnaire.File.QuestionnaireFileListJM () +import Wizard.Api.Resource.Questionnaire.QuestionnaireSimpleSM () +import Wizard.Database.Migration.Development.Questionnaire.Data.QuestionnaireFiles +import Wizard.Model.Questionnaire.QuestionnaireFileList +import WizardLib.Public.Api.Resource.User.UserSuggestionSM () + +instance ToSchema QuestionnaireFileList where + declareNamedSchema = toSwagger questionnaireFileList diff --git a/wizard-server/src/Wizard/Api/Resource/Questionnaire/File/QuestionnaireFileSimpleJM.hs b/wizard-server/src/Wizard/Api/Resource/Questionnaire/File/QuestionnaireFileSimpleJM.hs new file mode 100644 index 000000000..2c5da897d --- /dev/null +++ b/wizard-server/src/Wizard/Api/Resource/Questionnaire/File/QuestionnaireFileSimpleJM.hs @@ -0,0 +1,12 @@ +module Wizard.Api.Resource.Questionnaire.File.QuestionnaireFileSimpleJM where + +import Data.Aeson + +import Shared.Common.Util.Aeson +import Wizard.Model.Questionnaire.QuestionnaireFileSimple + +instance FromJSON QuestionnaireFileSimple where + parseJSON = genericParseJSON jsonOptions + +instance ToJSON QuestionnaireFileSimple where + toJSON = genericToJSON jsonOptions diff --git a/wizard-server/src/Wizard/Api/Resource/Questionnaire/File/QuestionnaireFileSimpleSM.hs b/wizard-server/src/Wizard/Api/Resource/Questionnaire/File/QuestionnaireFileSimpleSM.hs new file mode 100644 index 000000000..621e22fa2 --- /dev/null +++ b/wizard-server/src/Wizard/Api/Resource/Questionnaire/File/QuestionnaireFileSimpleSM.hs @@ -0,0 +1,11 @@ +module Wizard.Api.Resource.Questionnaire.File.QuestionnaireFileSimpleSM where + +import Data.Swagger + +import Shared.Common.Util.Swagger +import Wizard.Api.Resource.Questionnaire.File.QuestionnaireFileSimpleJM () +import Wizard.Database.Migration.Development.Questionnaire.Data.QuestionnaireFiles +import Wizard.Model.Questionnaire.QuestionnaireFileSimple + +instance ToSchema QuestionnaireFileSimple where + declareNamedSchema = toSwagger questionnaireFileSimple diff --git a/wizard-server/src/Wizard/Api/Resource/Questionnaire/QuestionnaireDetailDTO.hs b/wizard-server/src/Wizard/Api/Resource/Questionnaire/QuestionnaireDetailDTO.hs index 88017721c..a39ca685c 100644 --- a/wizard-server/src/Wizard/Api/Resource/Questionnaire/QuestionnaireDetailDTO.hs +++ b/wizard-server/src/Wizard/Api/Resource/Questionnaire/QuestionnaireDetailDTO.hs @@ -15,5 +15,6 @@ data QuestionnaireDetailDTO = QuestionnaireDetailDTO , isTemplate :: Bool , migrationUuid :: Maybe U.UUID , permissions :: [QuestionnairePermDTO] + , fileCount :: Int } deriving (Show, Eq, Generic) diff --git a/wizard-server/src/Wizard/Api/Resource/Questionnaire/QuestionnaireDetailPreviewSM.hs b/wizard-server/src/Wizard/Api/Resource/Questionnaire/QuestionnaireDetailPreviewSM.hs index 3eeead75c..7521b7a17 100644 --- a/wizard-server/src/Wizard/Api/Resource/Questionnaire/QuestionnaireDetailPreviewSM.hs +++ b/wizard-server/src/Wizard/Api/Resource/Questionnaire/QuestionnaireDetailPreviewSM.hs @@ -31,4 +31,5 @@ instance ToSchema QuestionnaireDetailPreview where , migrationUuid = Nothing , permissions = [qtn1AlbertEditQtnPermDto] , format = Just . DocumentTemplateMapper.toFormatDTO $ formatJson + , fileCount = 0 } diff --git a/wizard-server/src/Wizard/Api/Resource/Questionnaire/QuestionnaireDetailQuestionnaireDTO.hs b/wizard-server/src/Wizard/Api/Resource/Questionnaire/QuestionnaireDetailQuestionnaireDTO.hs index d36e2820c..3a59a5b8b 100644 --- a/wizard-server/src/Wizard/Api/Resource/Questionnaire/QuestionnaireDetailQuestionnaireDTO.hs +++ b/wizard-server/src/Wizard/Api/Resource/Questionnaire/QuestionnaireDetailQuestionnaireDTO.hs @@ -6,6 +6,7 @@ import GHC.Generics import Wizard.Api.Resource.Questionnaire.QuestionnairePermDTO import Wizard.Model.Questionnaire.Questionnaire +import Wizard.Model.Questionnaire.QuestionnaireFileSimple import Wizard.Model.Questionnaire.QuestionnaireReply import WizardLib.KnowledgeModel.Model.KnowledgeModel.KnowledgeModel @@ -23,9 +24,11 @@ data QuestionnaireDetailQuestionnaireDTO = QuestionnaireDetailQuestionnaireDTO , phaseUuid :: Maybe U.UUID , migrationUuid :: Maybe U.UUID , permissions :: [QuestionnairePermDTO] + , files :: [QuestionnaireFileSimple] , unresolvedCommentCounts :: M.Map String (M.Map U.UUID Int) , resolvedCommentCounts :: M.Map String (M.Map U.UUID Int) , questionnaireActionsAvailable :: Int , questionnaireImportersAvailable :: Int + , fileCount :: Int } deriving (Show, Eq, Generic) diff --git a/wizard-server/src/Wizard/Api/Resource/Questionnaire/QuestionnaireDetailQuestionnaireJM.hs b/wizard-server/src/Wizard/Api/Resource/Questionnaire/QuestionnaireDetailQuestionnaireJM.hs index 2f2d542ae..1994a36bb 100644 --- a/wizard-server/src/Wizard/Api/Resource/Questionnaire/QuestionnaireDetailQuestionnaireJM.hs +++ b/wizard-server/src/Wizard/Api/Resource/Questionnaire/QuestionnaireDetailQuestionnaireJM.hs @@ -3,6 +3,7 @@ module Wizard.Api.Resource.Questionnaire.QuestionnaireDetailQuestionnaireJM wher import Data.Aeson import Shared.Common.Util.Aeson +import Wizard.Api.Resource.Questionnaire.File.QuestionnaireFileSimpleJM () import Wizard.Api.Resource.Questionnaire.QuestionnaireDetailQuestionnaireDTO import Wizard.Api.Resource.Questionnaire.QuestionnairePermJM () import Wizard.Api.Resource.Questionnaire.QuestionnaireReplyJM () diff --git a/wizard-server/src/Wizard/Api/Resource/Questionnaire/QuestionnaireDetailQuestionnaireSM.hs b/wizard-server/src/Wizard/Api/Resource/Questionnaire/QuestionnaireDetailQuestionnaireSM.hs index 64d0d1502..f0dc7e86f 100644 --- a/wizard-server/src/Wizard/Api/Resource/Questionnaire/QuestionnaireDetailQuestionnaireSM.hs +++ b/wizard-server/src/Wizard/Api/Resource/Questionnaire/QuestionnaireDetailQuestionnaireSM.hs @@ -5,6 +5,7 @@ import Data.Swagger import Shared.Common.Util.Swagger import Shared.Common.Util.Uuid +import Wizard.Api.Resource.Questionnaire.File.QuestionnaireFileSimpleSM () import Wizard.Api.Resource.Questionnaire.QuestionnaireDetailQuestionnaireDTO import Wizard.Api.Resource.Questionnaire.QuestionnaireDetailQuestionnaireJM () import Wizard.Api.Resource.Questionnaire.QuestionnairePermSM () @@ -35,6 +36,7 @@ instance ToSchema QuestionnaireDetailQuestionnaireDTO where , phaseUuid = Just . u' $ "4b376e49-1589-429b-9590-c654378f0bd5" , migrationUuid = Nothing , permissions = [qtn1AlbertEditQtnPermDto] + , files = [] , unresolvedCommentCounts = M.fromList [ @@ -51,4 +53,5 @@ instance ToSchema QuestionnaireDetailQuestionnaireDTO where ] , questionnaireActionsAvailable = 1 , questionnaireImportersAvailable = 2 + , fileCount = 0 } diff --git a/wizard-server/src/Wizard/Api/Resource/Questionnaire/QuestionnaireDetailReportDTO.hs b/wizard-server/src/Wizard/Api/Resource/Questionnaire/QuestionnaireDetailReportDTO.hs index 77b478dd0..44d480b5f 100644 --- a/wizard-server/src/Wizard/Api/Resource/Questionnaire/QuestionnaireDetailReportDTO.hs +++ b/wizard-server/src/Wizard/Api/Resource/Questionnaire/QuestionnaireDetailReportDTO.hs @@ -17,6 +17,7 @@ data QuestionnaireDetailReportDTO = QuestionnaireDetailReportDTO , isTemplate :: Bool , migrationUuid :: Maybe U.UUID , permissions :: [QuestionnairePermDTO] + , fileCount :: Int , totalReport :: TotalReport , chapterReports :: [ChapterReport] , chapters :: [Chapter] diff --git a/wizard-server/src/Wizard/Api/Resource/Questionnaire/QuestionnaireDetailReportSM.hs b/wizard-server/src/Wizard/Api/Resource/Questionnaire/QuestionnaireDetailReportSM.hs index e30c19e8e..b978edad0 100644 --- a/wizard-server/src/Wizard/Api/Resource/Questionnaire/QuestionnaireDetailReportSM.hs +++ b/wizard-server/src/Wizard/Api/Resource/Questionnaire/QuestionnaireDetailReportSM.hs @@ -27,6 +27,7 @@ instance ToSchema QuestionnaireDetailReportDTO where , isTemplate = questionnaire1.isTemplate , migrationUuid = Nothing , permissions = [qtn1AlbertEditQtnPermDto] + , fileCount = 0 , totalReport = report1.totalReport , chapterReports = report1.chapterReports , chapters = report1.chapters diff --git a/wizard-server/src/Wizard/Api/Resource/Questionnaire/QuestionnaireDetailSM.hs b/wizard-server/src/Wizard/Api/Resource/Questionnaire/QuestionnaireDetailSM.hs index f552441bf..827daf8f4 100644 --- a/wizard-server/src/Wizard/Api/Resource/Questionnaire/QuestionnaireDetailSM.hs +++ b/wizard-server/src/Wizard/Api/Resource/Questionnaire/QuestionnaireDetailSM.hs @@ -23,4 +23,5 @@ instance ToSchema QuestionnaireDetailDTO where , isTemplate = questionnaire1.isTemplate , migrationUuid = Nothing , permissions = [qtn1AlbertEditQtnPermDto] + , fileCount = 0 } diff --git a/wizard-server/src/Wizard/Api/Resource/Questionnaire/QuestionnaireDetailSettingsSM.hs b/wizard-server/src/Wizard/Api/Resource/Questionnaire/QuestionnaireDetailSettingsSM.hs index 1066b9b27..c02358752 100644 --- a/wizard-server/src/Wizard/Api/Resource/Questionnaire/QuestionnaireDetailSettingsSM.hs +++ b/wizard-server/src/Wizard/Api/Resource/Questionnaire/QuestionnaireDetailSettingsSM.hs @@ -50,4 +50,5 @@ instance ToSchema QuestionnaireDetailSettings where , documentTemplateState = Just DefaultDocumentTemplateState , documentTemplatePhase = Just DraftDocumentTemplatePhase , formatUuid = Just . u' $ "ae3b9e68-e09e-4ad7-b476-67ab5626e873" + , fileCount = 0 } diff --git a/wizard-server/src/Wizard/Api/Resource/Websocket/QuestionnaireActionDTO.hs b/wizard-server/src/Wizard/Api/Resource/Websocket/QuestionnaireActionDTO.hs index 8c823438c..3f2e30d87 100644 --- a/wizard-server/src/Wizard/Api/Resource/Websocket/QuestionnaireActionDTO.hs +++ b/wizard-server/src/Wizard/Api/Resource/Websocket/QuestionnaireActionDTO.hs @@ -5,6 +5,7 @@ import GHC.Generics import Wizard.Api.Resource.Questionnaire.Event.QuestionnaireEventChangeDTO import Wizard.Api.Resource.Questionnaire.Event.QuestionnaireEventDTO import Wizard.Api.Resource.Questionnaire.QuestionnaireDetailWsDTO +import Wizard.Model.Questionnaire.QuestionnaireFileSimple import Wizard.Model.User.OnlineUserInfo data ClientQuestionnaireActionDTO = SetContent_ClientQuestionnaireActionDTO @@ -22,4 +23,7 @@ data ServerQuestionnaireActionDTO | SetQuestionnaire_ServerQuestionnaireActionDTO { sqData :: QuestionnaireDetailWsDTO } + | AddFile_ServerQuestionnaireActionDTO + { adData :: QuestionnaireFileSimple + } deriving (Show, Eq, Generic) diff --git a/wizard-server/src/Wizard/Api/Resource/Websocket/QuestionnaireActionJM.hs b/wizard-server/src/Wizard/Api/Resource/Websocket/QuestionnaireActionJM.hs index f04b669a4..a84f31dcf 100644 --- a/wizard-server/src/Wizard/Api/Resource/Websocket/QuestionnaireActionJM.hs +++ b/wizard-server/src/Wizard/Api/Resource/Websocket/QuestionnaireActionJM.hs @@ -5,6 +5,7 @@ import Data.Aeson import Shared.Common.Util.Aeson import Wizard.Api.Resource.Questionnaire.Event.QuestionnaireEventChangeJM () import Wizard.Api.Resource.Questionnaire.Event.QuestionnaireEventJM () +import Wizard.Api.Resource.Questionnaire.File.QuestionnaireFileSimpleJM () import Wizard.Api.Resource.Questionnaire.QuestionnaireDetailWsJM () import Wizard.Api.Resource.Questionnaire.QuestionnaireReplyJM () import Wizard.Api.Resource.User.OnlineUserInfoJM () diff --git a/wizard-server/src/Wizard/Api/Resource/Websocket/QuestionnaireActionSM.hs b/wizard-server/src/Wizard/Api/Resource/Websocket/QuestionnaireActionSM.hs index 1d1803b8f..a201f8a2f 100644 --- a/wizard-server/src/Wizard/Api/Resource/Websocket/QuestionnaireActionSM.hs +++ b/wizard-server/src/Wizard/Api/Resource/Websocket/QuestionnaireActionSM.hs @@ -5,6 +5,7 @@ import Data.Swagger import Shared.Common.Util.Swagger import Wizard.Api.Resource.Questionnaire.Event.QuestionnaireEventChangeSM () import Wizard.Api.Resource.Questionnaire.Event.QuestionnaireEventSM () +import Wizard.Api.Resource.Questionnaire.File.QuestionnaireFileSimpleSM () import Wizard.Api.Resource.Questionnaire.QuestionnaireDetailWsSM () import Wizard.Api.Resource.Questionnaire.QuestionnaireReplySM () import Wizard.Api.Resource.User.OnlineUserInfoSM () diff --git a/wizard-server/src/Wizard/Constant/Acl.hs b/wizard-server/src/Wizard/Constant/Acl.hs index bbc00d1a3..2a120cef4 100644 --- a/wizard-server/src/Wizard/Constant/Acl.hs +++ b/wizard-server/src/Wizard/Constant/Acl.hs @@ -7,6 +7,7 @@ module Wizard.Constant.Acl ( _PM_READ_PERM, _PM_WRITE_PERM, _QTN_PERM, + _QTN_FILE_PERM, _QTN_TML_PERM, _QTN_ACTION_PERM, _QTN_IMPORTER_PERM, @@ -33,6 +34,8 @@ _PM_WRITE_PERM = "PM_WRITE_PERM" _QTN_PERM = "QTN_PERM" +_QTN_FILE_PERM = "QTN_FILE_PERM" + _QTN_TML_PERM = "QTN_TML_PERM" _QTN_ACTION_PERM = "QTN_ACTION_PERM" diff --git a/wizard-server/src/Wizard/Database/DAO/Questionnaire/QuestionnaireDAO.hs b/wizard-server/src/Wizard/Database/DAO/Questionnaire/QuestionnaireDAO.hs index 91bf61db6..7ccb21dc6 100644 --- a/wizard-server/src/Wizard/Database/DAO/Questionnaire/QuestionnaireDAO.hs +++ b/wizard-server/src/Wizard/Database/DAO/Questionnaire/QuestionnaireDAO.hs @@ -24,6 +24,7 @@ import Wizard.Database.DAO.Questionnaire.QuestionnairePermDAO ( insertQuestionnairePerm, ) import Wizard.Database.Mapping.Questionnaire.Questionnaire () +import Wizard.Database.Mapping.Questionnaire.QuestionnaireDetail () import Wizard.Database.Mapping.Questionnaire.QuestionnaireDetailPreview () import Wizard.Database.Mapping.Questionnaire.QuestionnaireDetailQuestionnaire () import Wizard.Database.Mapping.Questionnaire.QuestionnaireDetailSettings () @@ -37,6 +38,7 @@ import Wizard.Model.Context.AppContext import Wizard.Model.Context.AppContextHelpers import Wizard.Model.Context.ContextLenses () import Wizard.Model.Questionnaire.Questionnaire +import Wizard.Model.Questionnaire.QuestionnaireDetail import Wizard.Model.Questionnaire.QuestionnaireDetailPreview import Wizard.Model.Questionnaire.QuestionnaireDetailQuestionnaire import Wizard.Model.Questionnaire.QuestionnaireDetailSettings @@ -399,7 +401,7 @@ findQuestionnaireSquashByUuid :: U.UUID -> AppContextM QuestionnaireSquash findQuestionnaireSquashByUuid uuid = createFindEntityWithFieldsByFn "uuid, events, versions" True entityName [("uuid", U.toString uuid)] -findQuestionnaireDetail :: U.UUID -> AppContextM QuestionnaireDetailQuestionnaire +findQuestionnaireDetail :: U.UUID -> AppContextM QuestionnaireDetail findQuestionnaireDetail uuid = do tenantUuid <- asks currentTenantUuid let sql = @@ -424,11 +426,65 @@ findQuestionnaireDetail uuid = do \ SELECT count(*) \ \ FROM questionnaire_importer \ \ WHERE tenant_uuid = '${tenantUuid}' \ - \ ) as questionnaire_impoters \ + \ ) as questionnaire_impoters, \ + \ ( \ + \ SELECT count(*) \ + \ FROM questionnaire_file \ + \ WHERE tenant_uuid = '${tenantUuid}' AND questionnaire_uuid = '${questionnaireUuid}' \ + \ ) as file_count \ \FROM questionnaire qtn \ \LEFT JOIN questionnaire_migration qtn_mig ON qtn.uuid = qtn_mig.old_questionnaire_uuid AND qtn.tenant_uuid = qtn_mig.tenant_uuid \ \WHERE qtn.tenant_uuid = ? AND qtn.uuid = ?" [ ("questionnaireDetailPermSql", questionnaireDetailPermSql) + , ("questionnaireUuid", U.toString uuid) + , ("tenantUuid", U.toString tenantUuid) + ] + let queryParams = [("tenant_uuid", U.toString tenantUuid), ("uuid", U.toString uuid)] + let params = fmap snd queryParams + logQuery sql params + let action conn = query conn sql params + runOneEntityDB entityName action queryParams + +findQuestionnaireDetailQuestionnaire :: U.UUID -> AppContextM QuestionnaireDetailQuestionnaire +findQuestionnaireDetailQuestionnaire uuid = do + tenantUuid <- asks currentTenantUuid + let sql = + fromString $ + f'' + "SELECT qtn.uuid, \ + \ qtn.name, \ + \ qtn.visibility, \ + \ qtn.sharing, \ + \ qtn.package_id, \ + \ qtn.selected_question_tag_uuids, \ + \ qtn.is_template, \ + \ qtn.events, \ + \ qtn_mig.new_questionnaire_uuid AS migration_uuid, \ + \ ${questionnaireDetailPermSql}, \ + \ ( \ + \ SELECT count(*) \ + \ FROM questionnaire_action \ + \ WHERE tenant_uuid = '${tenantUuid}' \ + \ ) as questionnaire_actions, \ + \ ( \ + \ SELECT count(*) \ + \ FROM questionnaire_importer \ + \ WHERE tenant_uuid = '${tenantUuid}' \ + \ ) as questionnaire_impoters, \ + \ ( \ + \ SELECT array_agg(concat(uuid, '<:::::>', \ + \ file_name, '<:::::>', \ + \ content_type, '<:::::>', \ + \ file_size \ + \ )) \ + \ FROM questionnaire_file \ + \ WHERE tenant_uuid = '${tenantUuid}' AND questionnaire_uuid = '${questionnaireUuid}' \ + \ ) as files \ + \FROM questionnaire qtn \ + \LEFT JOIN questionnaire_migration qtn_mig ON qtn.uuid = qtn_mig.old_questionnaire_uuid AND qtn.tenant_uuid = qtn_mig.tenant_uuid \ + \WHERE qtn.tenant_uuid = ? AND qtn.uuid = ?" + [ ("questionnaireUuid", U.toString uuid) + , ("questionnaireDetailPermSql", questionnaireDetailPermSql) , ("tenantUuid", U.toString tenantUuid) ] let queryParams = [("tenant_uuid", U.toString tenantUuid), ("uuid", U.toString uuid)] @@ -453,12 +509,20 @@ findQuestionnaireDetailPreview uuid = do \ qtn.format_uuid, \ \ qtn_mig.new_questionnaire_uuid AS migration_uuid, \ \ ${questionnaireDetailPermSql}, \ - \ dt.formats AS document_template_formats \ + \ dt.formats AS document_template_formats, \ + \ ( \ + \ SELECT count(*) \ + \ FROM questionnaire_file \ + \ WHERE tenant_uuid = '${tenantUuid}' AND questionnaire_uuid = '${questionnaireUuid}' \ + \ ) as file_count \ \FROM questionnaire qtn \ \LEFT JOIN questionnaire_migration qtn_mig ON qtn.uuid = qtn_mig.old_questionnaire_uuid AND qtn.tenant_uuid = qtn_mig.tenant_uuid \ \LEFT JOIN document_template dt ON qtn.document_template_id = dt.id AND qtn.tenant_uuid = dt.tenant_uuid \ \WHERE qtn.tenant_uuid = ? AND qtn.uuid = ?" - [("questionnaireDetailPermSql", questionnaireDetailPermSql)] + [ ("questionnaireDetailPermSql", questionnaireDetailPermSql) + , ("questionnaireUuid", U.toString uuid) + , ("tenantUuid", U.toString tenantUuid) + ] let queryParams = [("tenant_uuid", U.toString tenantUuid), ("uuid", U.toString uuid)] let params = fmap snd queryParams logQuery sql params @@ -497,13 +561,21 @@ findQuestionnaireDetailSettings uuid = do \ dt.phase as document_template_phase, \ \ dt.description as document_template_description, \ \ dt.formats as document_template_formats, \ - \ dt.metamodel_version as document_template_metamodel_version \ + \ dt.metamodel_version as document_template_metamodel_version, \ + \ ( \ + \ SELECT count(*) \ + \ FROM questionnaire_file \ + \ WHERE tenant_uuid = '${tenantUuid}' AND questionnaire_uuid = '${questionnaireUuid}' \ + \ ) as file_count \ \FROM questionnaire qtn \ \LEFT JOIN questionnaire_migration qtn_mig ON qtn.uuid = qtn_mig.old_questionnaire_uuid AND qtn.tenant_uuid = qtn_mig.tenant_uuid \ \LEFT JOIN package pkg ON qtn.package_id = pkg.id AND qtn.tenant_uuid = pkg.tenant_uuid \ \LEFT JOIN document_template dt ON qtn.document_template_id = dt.id AND qtn.tenant_uuid = dt.tenant_uuid \ \WHERE qtn.tenant_uuid = ? AND qtn.uuid = ?" - [("questionnaireDetailPermSql", questionnaireDetailPermSql)] + [ ("questionnaireDetailPermSql", questionnaireDetailPermSql) + , ("questionnaireUuid", U.toString uuid) + , ("tenantUuid", U.toString tenantUuid) + ] let queryParams = [("tenant_uuid", U.toString tenantUuid), ("uuid", U.toString uuid)] let params = fmap snd queryParams logQuery sql params diff --git a/wizard-server/src/Wizard/Database/DAO/Questionnaire/QuestionnaireFileDAO.hs b/wizard-server/src/Wizard/Database/DAO/Questionnaire/QuestionnaireFileDAO.hs new file mode 100644 index 000000000..c69deed24 --- /dev/null +++ b/wizard-server/src/Wizard/Database/DAO/Questionnaire/QuestionnaireFileDAO.hs @@ -0,0 +1,114 @@ +module Wizard.Database.DAO.Questionnaire.QuestionnaireFileDAO where + +import Control.Monad.Reader (asks) +import Data.String +import qualified Data.UUID as U +import Database.PostgreSQL.Simple +import GHC.Int + +import Shared.Common.Model.Common.Page +import Shared.Common.Model.Common.PageMetadata +import Shared.Common.Model.Common.Pageable +import Shared.Common.Model.Common.Sort +import Shared.Common.Util.String +import Wizard.Database.DAO.Common +import Wizard.Database.Mapping.Questionnaire.QuestionnaireFile () +import Wizard.Database.Mapping.Questionnaire.QuestionnaireFileList () +import Wizard.Database.Mapping.Questionnaire.QuestionnaireFileSimple () +import Wizard.Model.Context.AppContext +import Wizard.Model.Context.ContextLenses () +import Wizard.Model.Questionnaire.QuestionnaireFile +import Wizard.Model.Questionnaire.QuestionnaireFileList +import Wizard.Model.Questionnaire.QuestionnaireFileSimple + +entityName = "questionnaire_file" + +pageLabel = "questionnaireFiles" + +findQuestionnaireFilesPage :: Maybe String -> Maybe U.UUID -> Pageable -> [Sort] -> AppContextM (Page QuestionnaireFileList) +findQuestionnaireFilesPage mQuery mQtnUuid pageable sort = do + -- 1. Prepare variables + do + tenantUuid <- asks currentTenantUuid + let (queryCondition, queryParam) = + case mQuery of + Nothing -> ("", []) + Just query -> (" AND file_name ~* ?", [query]) + let (qtnUuidCondition, qtnUuidParam) = + case mQtnUuid of + Nothing -> ("", []) + Just qtnUuid -> (" AND questionnaire_uuid = ?", [U.toString qtnUuid]) + let condition = + f'' + "WHERE file.tenant_uuid = ? ${queryCondition} ${qtnUuidCondition}" + [ ("queryCondition", queryCondition) + , ("qtnUuidCondition", qtnUuidCondition) + ] + let conditionParams = + [U.toString tenantUuid] + ++ queryParam + ++ qtnUuidParam + let (sizeI, pageI, skip, limit) = preparePaginationVariables pageable + -- 2. Get total count + count <- createCountByFn "questionnaire_file file" condition conditionParams + -- 3. Get entities + let sql = + fromString $ + f'' + "SELECT file.uuid, \ + \ file.file_name, \ + \ file.content_type, \ + \ file.file_size, \ + \ file.created_at, \ + \ questionnaire.uuid, \ + \ questionnaire.name, \ + \ created_by.uuid, \ + \ created_by.first_name, \ + \ created_by.last_name, \ + \ created_by.email, \ + \ created_by.image_url \ + \FROM questionnaire_file file \ + \LEFT JOIN user_entity created_by ON created_by.uuid = file.created_by AND created_by.tenant_uuid = file.tenant_uuid \ + \LEFT JOIN questionnaire ON questionnaire.uuid = file.questionnaire_uuid AND questionnaire.tenant_uuid = file.tenant_uuid \ + \${condition} \ + \${sort} \ + \OFFSET ${offset} \ + \LIMIT ${limit}" + [ ("condition", condition) + , ("sort", mapSort sort) + , ("offset", show skip) + , ("limit", show sizeI) + ] + logQuery sql conditionParams + let action conn = query conn sql conditionParams + entities <- runDB action + -- 4. Constructor response + let metadata = + PageMetadata + { size = sizeI + , totalElements = count + , totalPages = computeTotalPage count sizeI + , number = pageI + } + return $ Page pageLabel metadata entities + +findQuestionnaireFilesByQuestionnaire :: U.UUID -> AppContextM [QuestionnaireFileSimple] +findQuestionnaireFilesByQuestionnaire qtnUuid = do + tenantUuid <- asks currentTenantUuid + createFindEntitiesWithFieldsByFn "uuid, file_name, content_type, file_size" entityName [tenantQueryUuid tenantUuid, ("questionnaire_uuid", U.toString qtnUuid)] + +findQuestionnaireFileByUuid :: U.UUID -> AppContextM QuestionnaireFile +findQuestionnaireFileByUuid uuid = do + tenantUuid <- asks currentTenantUuid + createFindEntityByFn entityName [tenantQueryUuid tenantUuid, ("uuid", U.toString uuid)] + +insertQuestionnaireFile :: QuestionnaireFile -> AppContextM Int64 +insertQuestionnaireFile = createInsertFn entityName + +deleteQuestionnaireFiles :: AppContextM Int64 +deleteQuestionnaireFiles = createDeleteEntitiesFn entityName + +deleteQuestionnaireFileByUuid :: U.UUID -> AppContextM Int64 +deleteQuestionnaireFileByUuid uuid = do + tenantUuid <- asks currentTenantUuid + createDeleteEntityByFn entityName [tenantQueryUuid tenantUuid, ("uuid", U.toString uuid)] diff --git a/wizard-server/src/Wizard/Database/Mapping/Questionnaire/QuestionnaireDetail.hs b/wizard-server/src/Wizard/Database/Mapping/Questionnaire/QuestionnaireDetail.hs new file mode 100644 index 000000000..5950f1160 --- /dev/null +++ b/wizard-server/src/Wizard/Database/Mapping/Questionnaire/QuestionnaireDetail.hs @@ -0,0 +1,29 @@ +module Wizard.Database.Mapping.Questionnaire.QuestionnaireDetail where + +import Database.PostgreSQL.Simple +import Database.PostgreSQL.Simple.FromField +import Database.PostgreSQL.Simple.FromRow + +import Wizard.Api.Resource.Questionnaire.Event.QuestionnaireEventJM () +import Wizard.Database.Mapping.Questionnaire.QuestionnaireAcl +import Wizard.Database.Mapping.Questionnaire.QuestionnaireSharing () +import Wizard.Database.Mapping.Questionnaire.QuestionnaireState () +import Wizard.Database.Mapping.Questionnaire.QuestionnaireVisibility () +import Wizard.Model.Questionnaire.QuestionnaireDetail + +instance FromRow QuestionnaireDetail where + fromRow = do + uuid <- field + name <- field + visibility <- field + sharing <- field + packageId <- field + selectedQuestionTagUuids <- fieldWith fromJSONField + isTemplate <- field + events <- fieldWith fromJSONField + migrationUuid <- field + permissions <- loadPermissions uuid + questionnaireActionsAvailable <- field + questionnaireImportersAvailable <- field + fileCount <- field + return $ QuestionnaireDetail {..} diff --git a/wizard-server/src/Wizard/Database/Mapping/Questionnaire/QuestionnaireDetailPreview.hs b/wizard-server/src/Wizard/Database/Mapping/Questionnaire/QuestionnaireDetailPreview.hs index fc568a080..019d44391 100644 --- a/wizard-server/src/Wizard/Database/Mapping/Questionnaire/QuestionnaireDetailPreview.hs +++ b/wizard-server/src/Wizard/Database/Mapping/Questionnaire/QuestionnaireDetailPreview.hs @@ -28,4 +28,5 @@ instance FromRow QuestionnaireDetailPreview where permissions <- loadPermissions uuid mDocumentTemplateFormats <- fieldWith (optionalField fromJSONField) let format = concatMaybe . fmap (L.find (\format -> Just format.uuid == mFormatUuid)) $ mDocumentTemplateFormats + fileCount <- field return $ QuestionnaireDetailPreview {..} diff --git a/wizard-server/src/Wizard/Database/Mapping/Questionnaire/QuestionnaireDetailQuestionnaire.hs b/wizard-server/src/Wizard/Database/Mapping/Questionnaire/QuestionnaireDetailQuestionnaire.hs index 39472a6ff..6239fd0b0 100644 --- a/wizard-server/src/Wizard/Database/Mapping/Questionnaire/QuestionnaireDetailQuestionnaire.hs +++ b/wizard-server/src/Wizard/Database/Mapping/Questionnaire/QuestionnaireDetailQuestionnaire.hs @@ -3,13 +3,18 @@ module Wizard.Database.Mapping.Questionnaire.QuestionnaireDetailQuestionnaire wh import Database.PostgreSQL.Simple import Database.PostgreSQL.Simple.FromField import Database.PostgreSQL.Simple.FromRow +import Database.PostgreSQL.Simple.Types +import Shared.Common.Util.String +import Shared.Common.Util.Uuid import Wizard.Api.Resource.Questionnaire.Event.QuestionnaireEventJM () import Wizard.Database.Mapping.Questionnaire.QuestionnaireAcl +import Wizard.Database.Mapping.Questionnaire.QuestionnaireFileSimple () import Wizard.Database.Mapping.Questionnaire.QuestionnaireSharing () import Wizard.Database.Mapping.Questionnaire.QuestionnaireState () import Wizard.Database.Mapping.Questionnaire.QuestionnaireVisibility () import Wizard.Model.Questionnaire.QuestionnaireDetailQuestionnaire +import Wizard.Model.Questionnaire.QuestionnaireFileSimple instance FromRow QuestionnaireDetailQuestionnaire where fromRow = do @@ -25,4 +30,19 @@ instance FromRow QuestionnaireDetailQuestionnaire where permissions <- loadPermissions uuid questionnaireActionsAvailable <- field questionnaireImportersAvailable <- field + mFiles <- fieldWith (optionalField fromField) + let files = + case mFiles of + Just files -> fmap parseFile . fromPGArray $ files + Nothing -> [] return $ QuestionnaireDetailQuestionnaire {..} + where + parseFile :: String -> QuestionnaireFileSimple + parseFile file = + let parts = splitOn "<:::::>" file + in QuestionnaireFileSimple + { uuid = u' $ head parts + , fileName = parts !! 1 + , contentType = parts !! 2 + , fileSize = read $ parts !! 3 + } diff --git a/wizard-server/src/Wizard/Database/Mapping/Questionnaire/QuestionnaireDetailSettings.hs b/wizard-server/src/Wizard/Database/Mapping/Questionnaire/QuestionnaireDetailSettings.hs index 513f6e72f..1da1a6b42 100644 --- a/wizard-server/src/Wizard/Database/Mapping/Questionnaire/QuestionnaireDetailSettings.hs +++ b/wizard-server/src/Wizard/Database/Mapping/Questionnaire/QuestionnaireDetailSettings.hs @@ -85,5 +85,5 @@ instance FromRow QuestionnaireDetailSettings where then Just UnsupportedMetamodelVersionDocumentTemplateState else Just DefaultDocumentTemplateState _ -> Nothing - + fileCount <- field return $ QuestionnaireDetailSettings {..} diff --git a/wizard-server/src/Wizard/Database/Mapping/Questionnaire/QuestionnaireFile.hs b/wizard-server/src/Wizard/Database/Mapping/Questionnaire/QuestionnaireFile.hs new file mode 100644 index 000000000..e95664ed0 --- /dev/null +++ b/wizard-server/src/Wizard/Database/Mapping/Questionnaire/QuestionnaireFile.hs @@ -0,0 +1,9 @@ +module Wizard.Database.Mapping.Questionnaire.QuestionnaireFile where + +import Database.PostgreSQL.Simple + +import Wizard.Model.Questionnaire.QuestionnaireFile + +instance ToRow QuestionnaireFile + +instance FromRow QuestionnaireFile diff --git a/wizard-server/src/Wizard/Database/Mapping/Questionnaire/QuestionnaireFileList.hs b/wizard-server/src/Wizard/Database/Mapping/Questionnaire/QuestionnaireFileList.hs new file mode 100644 index 000000000..53d005fa8 --- /dev/null +++ b/wizard-server/src/Wizard/Database/Mapping/Questionnaire/QuestionnaireFileList.hs @@ -0,0 +1,36 @@ +module Wizard.Database.Mapping.Questionnaire.QuestionnaireFileList where + +import Database.PostgreSQL.Simple +import Database.PostgreSQL.Simple.FromRow + +import Shared.Common.Util.Gravatar +import Wizard.Model.Questionnaire.QuestionnaireFileList +import Wizard.Model.Questionnaire.QuestionnaireSimple +import WizardLib.Public.Api.Resource.User.UserSuggestionDTO + +instance FromRow QuestionnaireFileList where + fromRow = do + uuid <- field + fileName <- field + contentType <- field + fileSize <- field + createdAt <- field + questionnaireUuid <- field + questionnaireName <- field + let questionnaire = + QuestionnaireSimple + { uuid = questionnaireUuid + , name = questionnaireName + } + createdByUuid <- field + createdByFirstName <- field + createdByLastName <- field + createdByEmail <- field + createdByImageUrl <- field + let createdBy = + case (createdByUuid, createdByFirstName, createdByLastName, createdByEmail, createdByImageUrl) of + (Just uuid, Just firstName, Just lastName, Just email, imageUrl) -> + let gravatarHash = createGravatarHash email + in Just UserSuggestionDTO {..} + _ -> Nothing + return $ QuestionnaireFileList {..} diff --git a/wizard-server/src/Wizard/Database/Mapping/Questionnaire/QuestionnaireFileSimple.hs b/wizard-server/src/Wizard/Database/Mapping/Questionnaire/QuestionnaireFileSimple.hs new file mode 100644 index 000000000..0d4ab674a --- /dev/null +++ b/wizard-server/src/Wizard/Database/Mapping/Questionnaire/QuestionnaireFileSimple.hs @@ -0,0 +1,7 @@ +module Wizard.Database.Mapping.Questionnaire.QuestionnaireFileSimple where + +import Database.PostgreSQL.Simple + +import Wizard.Model.Questionnaire.QuestionnaireFileSimple + +instance FromRow QuestionnaireFileSimple diff --git a/wizard-server/src/Wizard/Database/Migration/Development/Document/Data/Documents.hs b/wizard-server/src/Wizard/Database/Migration/Development/Document/Data/Documents.hs index bf91c5afb..57be73297 100644 --- a/wizard-server/src/Wizard/Database/Migration/Development/Document/Data/Documents.hs +++ b/wizard-server/src/Wizard/Database/Migration/Development/Document/Data/Documents.hs @@ -91,6 +91,7 @@ dmp1 = , versionUuid = Nothing , versions = fmap (`toVersionDTO` Just userAlbert) questionnaire1.versions , projectTags = questionnaire1.projectTags + , files = [] , createdBy = Just . USR_Mapper.toDTO $ userAlbert , createdAt = questionnaire1.createdAt , updatedAt = questionnaire1.updatedAt diff --git a/wizard-server/src/Wizard/Database/Migration/Development/Questionnaire/Data/QuestionnaireFiles.hs b/wizard-server/src/Wizard/Database/Migration/Development/Questionnaire/Data/QuestionnaireFiles.hs new file mode 100644 index 000000000..fc76c0200 --- /dev/null +++ b/wizard-server/src/Wizard/Database/Migration/Development/Questionnaire/Data/QuestionnaireFiles.hs @@ -0,0 +1,33 @@ +module Wizard.Database.Migration.Development.Questionnaire.Data.QuestionnaireFiles where + +import Shared.Common.Util.Date +import Shared.Common.Util.Uuid +import Wizard.Database.Migration.Development.User.Data.Users +import Wizard.Model.Questionnaire.QuestionnaireFileList +import Wizard.Model.Questionnaire.QuestionnaireFileSimple +import Wizard.Model.Questionnaire.QuestionnaireSimple + +questionnaireFileList :: QuestionnaireFileList +questionnaireFileList = + QuestionnaireFileList + { uuid = u' "e3726571-f81e-4e34-a17a-2f5714b7aade" + , fileName = "my_file.txt" + , contentType = "application/json" + , fileSize = 123456 + , questionnaire = + QuestionnaireSimple + { uuid = u' "af984a75-56e3-49f8-b16f-d6b99599910a" + , name = "My Private Questionnaire" + } + , createdBy = Just userAlbertSuggestion + , createdAt = dt' 2018 01 21 + } + +questionnaireFileSimple :: QuestionnaireFileSimple +questionnaireFileSimple = + QuestionnaireFileSimple + { uuid = questionnaireFileList.uuid + , fileName = questionnaireFileList.fileName + , contentType = questionnaireFileList.contentType + , fileSize = questionnaireFileList.fileSize + } diff --git a/wizard-server/src/Wizard/Database/Migration/Development/Questionnaire/QuestionnaireMigration.hs b/wizard-server/src/Wizard/Database/Migration/Development/Questionnaire/QuestionnaireMigration.hs index 0d5d14f82..a1ed04a36 100644 --- a/wizard-server/src/Wizard/Database/Migration/Development/Questionnaire/QuestionnaireMigration.hs +++ b/wizard-server/src/Wizard/Database/Migration/Development/Questionnaire/QuestionnaireMigration.hs @@ -5,14 +5,18 @@ import Shared.Common.Util.Logger import Wizard.Database.DAO.Questionnaire.QuestionnaireCommentDAO import Wizard.Database.DAO.Questionnaire.QuestionnaireCommentThreadDAO import Wizard.Database.DAO.Questionnaire.QuestionnaireDAO +import Wizard.Database.DAO.Questionnaire.QuestionnaireFileDAO import Wizard.Database.DAO.Questionnaire.QuestionnairePermDAO import Wizard.Database.Migration.Development.Questionnaire.Data.QuestionnaireComments import Wizard.Database.Migration.Development.Questionnaire.Data.Questionnaires +import Wizard.S3.Questionnaire.QuestionnaireFileS3 import WizardLib.KnowledgeModel.Database.DAO.Package.PackageDAO import WizardLib.KnowledgeModel.Database.Migration.Development.Package.Data.Packages runMigration = do logInfo _CMP_MIGRATION "(Questionnaire/Questionnaire) started" + deleteQuestionnaireFiles + purgeBucket deleteQuestionnaireComments deleteQuestionnaireCommentThreads deleteQuestionnairePerms diff --git a/wizard-server/src/Wizard/Database/Migration/Development/Questionnaire/QuestionnaireSchemaMigration.hs b/wizard-server/src/Wizard/Database/Migration/Development/Questionnaire/QuestionnaireSchemaMigration.hs index 998055108..87929bb9b 100644 --- a/wizard-server/src/Wizard/Database/Migration/Development/Questionnaire/QuestionnaireSchemaMigration.hs +++ b/wizard-server/src/Wizard/Database/Migration/Development/Questionnaire/QuestionnaireSchemaMigration.hs @@ -1,5 +1,6 @@ module Wizard.Database.Migration.Development.Questionnaire.QuestionnaireSchemaMigration where +import Control.Monad.Except (catchError) import Database.PostgreSQL.Simple import GHC.Int @@ -7,12 +8,14 @@ import Shared.Common.Util.Logger import Wizard.Database.DAO.Common import Wizard.Model.Context.AppContext import Wizard.Model.Context.ContextLenses () +import Wizard.S3.Questionnaire.QuestionnaireFileS3 dropTables :: AppContextM Int64 dropTables = do logInfo _CMP_MIGRATION "(Table/Questionnaire) drop tables" let sql = - "DROP TABLE IF EXISTS questionnaire_comment CASCADE; \ + "DROP TABLE IF EXISTS questionnaire_file CASCADE; \ + \DROP TABLE IF EXISTS questionnaire_comment CASCADE; \ \DROP TABLE IF EXISTS questionnaire_comment_thread CASCADE; \ \DROP TABLE IF EXISTS questionnaire_perm_group CASCADE; \ \DROP TABLE IF EXISTS questionnaire_perm_user CASCADE; \ @@ -20,13 +23,20 @@ dropTables = do let action conn = execute_ conn sql runDB action -createTables :: AppContextM Int64 +dropBucket :: AppContextM () +dropBucket = do + catchError purgeBucket (\e -> return ()) + catchError removeBucket (\e -> return ()) + +createTables :: AppContextM () createTables = do createQtnTable createQtnAclUserTable createQtnAclGroupTable createQtnCommentThreadTable createQtnCommentTable + createQtnFileTable + makeBucket createQtnTable = do logInfo _CMP_MIGRATION "(Table/Questionnaire) create table" @@ -138,3 +148,24 @@ createQtnCommentTable = do \);" let action conn = execute_ conn sql runDB action + +createQtnFileTable = do + logInfo _CMP_MIGRATION "(Table/QuestionnaireFile) create table" + let sql = + "CREATE TABLE questionnaire_file \ + \( \ + \ uuid uuid NOT NULL, \ + \ file_name varchar NOT NULL, \ + \ content_type varchar NOT NULL, \ + \ file_size bigint NOT NULL, \ + \ questionnaire_uuid uuid NOT NULL, \ + \ created_by uuid, \ + \ tenant_uuid uuid NOT NULL, \ + \ created_at timestamptz NOT NULL, \ + \ CONSTRAINT questionnaire_file_pk PRIMARY KEY (uuid, tenant_uuid), \ + \ CONSTRAINT questionnaire_file_questionnaire_uuid_fk FOREIGN KEY (questionnaire_uuid, tenant_uuid) REFERENCES questionnaire (uuid, tenant_uuid), \ + \ CONSTRAINT questionnaire_file_user_uuid_fk FOREIGN KEY (created_by, tenant_uuid) REFERENCES user_entity (uuid, tenant_uuid), \ + \ CONSTRAINT questionnaire_file_tenant_uuid_fk FOREIGN KEY (tenant_uuid) REFERENCES tenant (uuid) \ + \);" + let action conn = execute_ conn sql + runDB action diff --git a/wizard-server/src/Wizard/Database/Migration/Development/Report/Data/Reports.hs b/wizard-server/src/Wizard/Database/Migration/Development/Report/Data/Reports.hs index 693819c06..41520e13d 100644 --- a/wizard-server/src/Wizard/Database/Migration/Development/Report/Data/Reports.hs +++ b/wizard-server/src/Wizard/Database/Migration/Development/Report/Data/Reports.hs @@ -32,7 +32,7 @@ report1_total = , unansweredQuestions = 1 } , AnsweredIndication' $ - AnsweredIndication {answeredQuestions = 13, unansweredQuestions = 3} + AnsweredIndication {answeredQuestions = 13, unansweredQuestions = 4} ] , metrics = [ MetricSummary {metricUuid = metricF.uuid, measure = Just 1.0} @@ -52,7 +52,7 @@ report1_total_full = , unansweredQuestions = 1 } , AnsweredIndication' $ - AnsweredIndication {answeredQuestions = 13, unansweredQuestions = 3} + AnsweredIndication {answeredQuestions = 13, unansweredQuestions = 4} ] , metrics = [ MetricSummary {metricUuid = metricF.uuid, measure = Just 1.0} @@ -127,7 +127,7 @@ report1_ch3 = , unansweredQuestions = 0 } , AnsweredIndication' $ - AnsweredIndication {answeredQuestions = 3, unansweredQuestions = 2} + AnsweredIndication {answeredQuestions = 3, unansweredQuestions = 3} ] , metrics = [] } @@ -152,7 +152,7 @@ questionnaireReport = , unansweredQuestions = 1 } , AnsweredIndication' $ - AnsweredIndication {answeredQuestions = 13, unansweredQuestions = 3} + AnsweredIndication {answeredQuestions = 13, unansweredQuestions = 4} ] } diff --git a/wizard-server/src/Wizard/Database/Migration/Production/Migration.hs b/wizard-server/src/Wizard/Database/Migration/Production/Migration.hs index 3bee7f9ff..ab1113ef6 100644 --- a/wizard-server/src/Wizard/Database/Migration/Production/Migration.hs +++ b/wizard-server/src/Wizard/Database/Migration/Production/Migration.hs @@ -50,6 +50,7 @@ import qualified Wizard.Database.Migration.Production.Migration_0045_analytics.M import qualified Wizard.Database.Migration.Production.Migration_0046_tenantFeature.Migration as M_0046 import qualified Wizard.Database.Migration.Production.Migration_0047_qtnCommentAssignedTo.Migration as M_0047 import qualified Wizard.Database.Migration.Production.Migration_0048_jsonb.Migration as M_0048 +import qualified Wizard.Database.Migration.Production.Migration_0049_questionnaireFile.Migration as M_0049 migrationDefinitions :: [MigrationDefinition] migrationDefinitions = @@ -101,4 +102,5 @@ migrationDefinitions = , M_0046.definition , M_0047.definition , M_0048.definition + , M_0049.definition ] diff --git a/wizard-server/src/Wizard/Database/Migration/Production/Migration_0049_questionnaireFile/Migration.hs b/wizard-server/src/Wizard/Database/Migration/Production/Migration_0049_questionnaireFile/Migration.hs new file mode 100644 index 000000000..a9e0db331 --- /dev/null +++ b/wizard-server/src/Wizard/Database/Migration/Production/Migration_0049_questionnaireFile/Migration.hs @@ -0,0 +1,45 @@ +module Wizard.Database.Migration.Production.Migration_0049_questionnaireFile.Migration ( + definition, +) where + +import Control.Monad.Logger +import Control.Monad.Reader (liftIO) +import Data.Pool (Pool, withResource) +import Database.PostgreSQL.Migration.Entity +import Database.PostgreSQL.Simple + +definition = (meta, migrate) + +meta = MigrationMeta {mmNumber = 49, mmName = "Add Questionnaire File", mmDescription = "Add support for questionnaire file"} + +migrate :: Pool Connection -> LoggingT IO (Maybe Error) +migrate dbPool = do + createQtnFileTable dbPool + addQtnFileRole dbPool + +createQtnFileTable dbPool = do + let sql = + "CREATE TABLE questionnaire_file \ + \( \ + \ uuid uuid NOT NULL, \ + \ file_name varchar NOT NULL, \ + \ content_type varchar NOT NULL, \ + \ file_size bigint NOT NULL, \ + \ questionnaire_uuid uuid NOT NULL, \ + \ created_by uuid, \ + \ tenant_uuid uuid NOT NULL, \ + \ created_at timestamptz NOT NULL, \ + \ CONSTRAINT questionnaire_file_pk PRIMARY KEY (uuid, tenant_uuid), \ + \ CONSTRAINT questionnaire_file_questionnaire_uuid_fk FOREIGN KEY (questionnaire_uuid, tenant_uuid) REFERENCES questionnaire (uuid, tenant_uuid), \ + \ CONSTRAINT questionnaire_file_user_uuid_fk FOREIGN KEY (created_by, tenant_uuid) REFERENCES user_entity (uuid, tenant_uuid), \ + \ CONSTRAINT questionnaire_file_tenant_uuid_fk FOREIGN KEY (tenant_uuid) REFERENCES tenant (uuid) \ + \);" + let action conn = execute_ conn sql + liftIO $ withResource dbPool action + return Nothing + +addQtnFileRole dbPool = do + let sql = "UPDATE user_entity set permissions = permissions || '{QTN_FILE_PERM}' WHERE role = 'admin';" + let action conn = execute_ conn sql + liftIO $ withResource dbPool action + return Nothing diff --git a/wizard-server/src/Wizard/Model/Config/ServerConfig.hs b/wizard-server/src/Wizard/Model/Config/ServerConfig.hs index 8be5eec15..e3cf17191 100644 --- a/wizard-server/src/Wizard/Model/Config/ServerConfig.hs +++ b/wizard-server/src/Wizard/Model/Config/ServerConfig.hs @@ -102,6 +102,7 @@ data ServerConfigSignalBridge = ServerConfigSignalBridge , updatePermsArn :: String , updateUserGroupArn :: String , setQuestionnaireArn :: String + , addFileArn :: String , logOutAllArn :: String } deriving (Generic, Show) diff --git a/wizard-server/src/Wizard/Model/Config/ServerConfigDM.hs b/wizard-server/src/Wizard/Model/Config/ServerConfigDM.hs index 7c4c33ca3..cd3e7938f 100644 --- a/wizard-server/src/Wizard/Model/Config/ServerConfigDM.hs +++ b/wizard-server/src/Wizard/Model/Config/ServerConfigDM.hs @@ -178,6 +178,7 @@ defaultSignalBridge = , updatePermsArn = "" , updateUserGroupArn = "" , setQuestionnaireArn = "" + , addFileArn = "" , logOutAllArn = "" } diff --git a/wizard-server/src/Wizard/Model/Config/ServerConfigIM.hs b/wizard-server/src/Wizard/Model/Config/ServerConfigIM.hs index 8330f628e..992ed0ebf 100644 --- a/wizard-server/src/Wizard/Model/Config/ServerConfigIM.hs +++ b/wizard-server/src/Wizard/Model/Config/ServerConfigIM.hs @@ -135,6 +135,7 @@ instance FromEnv ServerConfigSignalBridge where , \c -> applyStringEnvVariable "SIGNAL_BRIDGE_UPDATE_PERMS_ARN" c.updatePermsArn (\x -> c {updatePermsArn = x} :: ServerConfigSignalBridge) , \c -> applyStringEnvVariable "SIGNAL_BRIDGE_UPDATE_USER_GROUP_ARN" c.updateUserGroupArn (\x -> c {updateUserGroupArn = x} :: ServerConfigSignalBridge) , \c -> applyStringEnvVariable "SIGNAL_BRIDGE_SET_QUESTIONNAIRE_ARN" c.setQuestionnaireArn (\x -> c {setQuestionnaireArn = x} :: ServerConfigSignalBridge) + , \c -> applyStringEnvVariable "SIGNAL_BRIDGE_ADD_FILE_ARN" c.addFileArn (\x -> c {addFileArn = x} :: ServerConfigSignalBridge) , \c -> applyStringEnvVariable "SIGNAL_BRIDGE_LOG_OUT_ALL_ARN" c.logOutAllArn (\x -> c {logOutAllArn = x} :: ServerConfigSignalBridge) ] diff --git a/wizard-server/src/Wizard/Model/Config/ServerConfigJM.hs b/wizard-server/src/Wizard/Model/Config/ServerConfigJM.hs index a51ba0cac..9df15dcdf 100644 --- a/wizard-server/src/Wizard/Model/Config/ServerConfigJM.hs +++ b/wizard-server/src/Wizard/Model/Config/ServerConfigJM.hs @@ -130,6 +130,7 @@ instance FromJSON ServerConfigSignalBridge where updatePermsArn <- o .:? "updatePermsArn" .!= defaultSignalBridge.updatePermsArn updateUserGroupArn <- o .:? "updateUserGroupArn" .!= defaultSignalBridge.updateUserGroupArn setQuestionnaireArn <- o .:? "setQuestionnaireArn" .!= defaultSignalBridge.setQuestionnaireArn + addFileArn <- o .:? "addFileArn" .!= defaultSignalBridge.addFileArn logOutAllArn <- o .:? "logOutAllArn" .!= defaultSignalBridge.logOutAllArn return ServerConfigSignalBridge {..} parseJSON _ = mzero diff --git a/wizard-server/src/Wizard/Model/Document/DocumentContext.hs b/wizard-server/src/Wizard/Model/Document/DocumentContext.hs index 6051e33d0..2178b1039 100644 --- a/wizard-server/src/Wizard/Model/Document/DocumentContext.hs +++ b/wizard-server/src/Wizard/Model/Document/DocumentContext.hs @@ -7,6 +7,7 @@ import GHC.Generics import Wizard.Api.Resource.Questionnaire.Version.QuestionnaireVersionDTO import Wizard.Api.Resource.User.UserDTO +import Wizard.Model.Questionnaire.QuestionnaireFileSimple import Wizard.Model.Questionnaire.QuestionnaireReply import Wizard.Model.Registry.RegistryOrganization import Wizard.Model.Report.Report @@ -57,6 +58,7 @@ data DocumentContextQuestionnaire = DocumentContextQuestionnaire , versionUuid :: Maybe U.UUID , versions :: [QuestionnaireVersionDTO] , projectTags :: [String] + , files :: [QuestionnaireFileSimple] , createdBy :: Maybe UserDTO , createdAt :: UTCTime , updatedAt :: UTCTime diff --git a/wizard-server/src/Wizard/Model/Document/DocumentContextJM.hs b/wizard-server/src/Wizard/Model/Document/DocumentContextJM.hs index 7b022bab5..3db83d9b5 100644 --- a/wizard-server/src/Wizard/Model/Document/DocumentContextJM.hs +++ b/wizard-server/src/Wizard/Model/Document/DocumentContextJM.hs @@ -4,6 +4,7 @@ import Data.Aeson import Shared.Common.Util.Aeson import Wizard.Api.Resource.Package.PackageSimpleJM () +import Wizard.Api.Resource.Questionnaire.File.QuestionnaireFileSimpleJM () import Wizard.Api.Resource.Questionnaire.QuestionnaireCommentThreadListJM () import Wizard.Api.Resource.Questionnaire.QuestionnaireReplyJM () import Wizard.Api.Resource.Questionnaire.Version.QuestionnaireVersionJM () diff --git a/wizard-server/src/Wizard/Model/Questionnaire/QuestionnaireDetail.hs b/wizard-server/src/Wizard/Model/Questionnaire/QuestionnaireDetail.hs new file mode 100644 index 000000000..ce9d56b52 --- /dev/null +++ b/wizard-server/src/Wizard/Model/Questionnaire/QuestionnaireDetail.hs @@ -0,0 +1,25 @@ +module Wizard.Model.Questionnaire.QuestionnaireDetail where + +import qualified Data.UUID as U +import GHC.Generics + +import Wizard.Api.Resource.Questionnaire.QuestionnairePermDTO +import Wizard.Model.Questionnaire.Questionnaire +import Wizard.Model.Questionnaire.QuestionnaireEvent + +data QuestionnaireDetail = QuestionnaireDetail + { uuid :: U.UUID + , name :: String + , visibility :: QuestionnaireVisibility + , sharing :: QuestionnaireSharing + , packageId :: String + , selectedQuestionTagUuids :: [U.UUID] + , isTemplate :: Bool + , migrationUuid :: Maybe U.UUID + , permissions :: [QuestionnairePermDTO] + , events :: [QuestionnaireEvent] + , questionnaireActionsAvailable :: Int + , questionnaireImportersAvailable :: Int + , fileCount :: Int + } + deriving (Show, Eq, Generic) diff --git a/wizard-server/src/Wizard/Model/Questionnaire/QuestionnaireDetailPreview.hs b/wizard-server/src/Wizard/Model/Questionnaire/QuestionnaireDetailPreview.hs index 04e0ef601..3fb6291cf 100644 --- a/wizard-server/src/Wizard/Model/Questionnaire/QuestionnaireDetailPreview.hs +++ b/wizard-server/src/Wizard/Model/Questionnaire/QuestionnaireDetailPreview.hs @@ -18,5 +18,6 @@ data QuestionnaireDetailPreview = QuestionnaireDetailPreview , permissions :: [QuestionnairePermDTO] , documentTemplateId :: Maybe String , format :: Maybe DocumentTemplateFormatDTO + , fileCount :: Int } deriving (Show, Eq, Generic) diff --git a/wizard-server/src/Wizard/Model/Questionnaire/QuestionnaireDetailQuestionnaire.hs b/wizard-server/src/Wizard/Model/Questionnaire/QuestionnaireDetailQuestionnaire.hs index 95db76462..e21c79bce 100644 --- a/wizard-server/src/Wizard/Model/Questionnaire/QuestionnaireDetailQuestionnaire.hs +++ b/wizard-server/src/Wizard/Model/Questionnaire/QuestionnaireDetailQuestionnaire.hs @@ -6,6 +6,7 @@ import GHC.Generics import Wizard.Api.Resource.Questionnaire.QuestionnairePermDTO import Wizard.Model.Questionnaire.Questionnaire import Wizard.Model.Questionnaire.QuestionnaireEvent +import Wizard.Model.Questionnaire.QuestionnaireFileSimple data QuestionnaireDetailQuestionnaire = QuestionnaireDetailQuestionnaire { uuid :: U.UUID @@ -18,6 +19,7 @@ data QuestionnaireDetailQuestionnaire = QuestionnaireDetailQuestionnaire , migrationUuid :: Maybe U.UUID , permissions :: [QuestionnairePermDTO] , events :: [QuestionnaireEvent] + , files :: [QuestionnaireFileSimple] , questionnaireActionsAvailable :: Int , questionnaireImportersAvailable :: Int } diff --git a/wizard-server/src/Wizard/Model/Questionnaire/QuestionnaireDetailSettings.hs b/wizard-server/src/Wizard/Model/Questionnaire/QuestionnaireDetailSettings.hs index d337d9eaf..a11124c91 100644 --- a/wizard-server/src/Wizard/Model/Questionnaire/QuestionnaireDetailSettings.hs +++ b/wizard-server/src/Wizard/Model/Questionnaire/QuestionnaireDetailSettings.hs @@ -29,5 +29,6 @@ data QuestionnaireDetailSettings = QuestionnaireDetailSettings , documentTemplatePhase :: Maybe DocumentTemplatePhase , formatUuid :: Maybe U.UUID , selectedQuestionTagUuids :: [U.UUID] + , fileCount :: Int } deriving (Show, Eq, Generic) diff --git a/wizard-server/src/Wizard/Model/Questionnaire/QuestionnaireFile.hs b/wizard-server/src/Wizard/Model/Questionnaire/QuestionnaireFile.hs new file mode 100644 index 000000000..ae4bf1f86 --- /dev/null +++ b/wizard-server/src/Wizard/Model/Questionnaire/QuestionnaireFile.hs @@ -0,0 +1,18 @@ +module Wizard.Model.Questionnaire.QuestionnaireFile where + +import Data.Time +import qualified Data.UUID as U +import GHC.Generics +import GHC.Int + +data QuestionnaireFile = QuestionnaireFile + { uuid :: U.UUID + , fileName :: String + , contentType :: String + , fileSize :: Int64 + , questionnaireUuid :: U.UUID + , createdBy :: Maybe U.UUID + , tenantUuid :: U.UUID + , createdAt :: UTCTime + } + deriving (Show, Eq, Generic) diff --git a/wizard-server/src/Wizard/Model/Questionnaire/QuestionnaireFileList.hs b/wizard-server/src/Wizard/Model/Questionnaire/QuestionnaireFileList.hs new file mode 100644 index 000000000..71fbf30f4 --- /dev/null +++ b/wizard-server/src/Wizard/Model/Questionnaire/QuestionnaireFileList.hs @@ -0,0 +1,20 @@ +module Wizard.Model.Questionnaire.QuestionnaireFileList where + +import Data.Time +import qualified Data.UUID as U +import GHC.Generics +import GHC.Int + +import Wizard.Model.Questionnaire.QuestionnaireSimple +import WizardLib.Public.Api.Resource.User.UserSuggestionDTO + +data QuestionnaireFileList = QuestionnaireFileList + { uuid :: U.UUID + , fileName :: String + , contentType :: String + , fileSize :: Int64 + , questionnaire :: QuestionnaireSimple + , createdBy :: Maybe UserSuggestionDTO + , createdAt :: UTCTime + } + deriving (Show, Eq, Generic) diff --git a/wizard-server/src/Wizard/Model/Questionnaire/QuestionnaireFileSimple.hs b/wizard-server/src/Wizard/Model/Questionnaire/QuestionnaireFileSimple.hs new file mode 100644 index 000000000..e0a92d741 --- /dev/null +++ b/wizard-server/src/Wizard/Model/Questionnaire/QuestionnaireFileSimple.hs @@ -0,0 +1,13 @@ +module Wizard.Model.Questionnaire.QuestionnaireFileSimple where + +import qualified Data.UUID as U +import GHC.Generics +import GHC.Int + +data QuestionnaireFileSimple = QuestionnaireFileSimple + { uuid :: U.UUID + , fileName :: String + , contentType :: String + , fileSize :: Int64 + } + deriving (Show, Eq, Generic) diff --git a/wizard-server/src/Wizard/Model/Questionnaire/QuestionnaireReply.hs b/wizard-server/src/Wizard/Model/Questionnaire/QuestionnaireReply.hs index 681be5dac..ca317c2ed 100644 --- a/wizard-server/src/Wizard/Model/Questionnaire/QuestionnaireReply.hs +++ b/wizard-server/src/Wizard/Model/Questionnaire/QuestionnaireReply.hs @@ -39,6 +39,9 @@ data ReplyValue | ItemSelectReply { isValue :: U.UUID } + | FileReply + { fValue :: U.UUID + } deriving (Show, Eq, Generic) instance Hashable ReplyValue diff --git a/wizard-server/src/Wizard/S3/Questionnaire/QuestionnaireFileS3.hs b/wizard-server/src/Wizard/S3/Questionnaire/QuestionnaireFileS3.hs new file mode 100644 index 000000000..2e83c960e --- /dev/null +++ b/wizard-server/src/Wizard/S3/Questionnaire/QuestionnaireFileS3.hs @@ -0,0 +1,35 @@ +module Wizard.S3.Questionnaire.QuestionnaireFileS3 where + +import qualified Data.ByteString.Char8 as BS +import qualified Data.UUID as U + +import Shared.Common.S3.Common +import Shared.Common.Util.String (f') +import Wizard.Model.Context.AppContext +import Wizard.Model.Context.ContextLenses () + +folderName = "templates" + +retrieveFile :: U.UUID -> U.UUID -> AppContextM BS.ByteString +retrieveFile questionnaireUuid fileUuid = createGetObjectFn (f' "%s/%s/%s" [folderName, U.toString questionnaireUuid, U.toString fileUuid]) + +putFile :: U.UUID -> U.UUID -> String -> BS.ByteString -> AppContextM String +putFile questionnaireUuid fileUuid contentType = createPutObjectFn (f' "%s/%s/%s" [folderName, U.toString questionnaireUuid, U.toString fileUuid]) (Just contentType) Nothing + +presigneGetFileUrl :: U.UUID -> U.UUID -> Int -> AppContextM String +presigneGetFileUrl questionnaireUuid fileUuid = createPresignedGetObjectUrl (f' "%s/%s/%s" [folderName, U.toString questionnaireUuid, U.toString fileUuid]) + +removeFiles :: U.UUID -> AppContextM () +removeFiles questionnaireUuid = createRemoveObjectFn (f' "%s/%s" [folderName, U.toString questionnaireUuid]) + +removeFile :: U.UUID -> U.UUID -> AppContextM () +removeFile questionnaireUuid fileUuid = createRemoveObjectFn (f' "%s/%s/%s" [folderName, U.toString questionnaireUuid, U.toString fileUuid]) + +makeBucket :: AppContextM () +makeBucket = createMakeBucketFn + +purgeBucket :: AppContextM () +purgeBucket = createPurgeBucketFn + +removeBucket :: AppContextM () +removeBucket = createRemoveBucketFn diff --git a/wizard-server/src/Wizard/Service/Document/Context/DocumentContextMapper.hs b/wizard-server/src/Wizard/Service/Document/Context/DocumentContextMapper.hs index 006e363f2..90e729050 100644 --- a/wizard-server/src/Wizard/Service/Document/Context/DocumentContextMapper.hs +++ b/wizard-server/src/Wizard/Service/Document/Context/DocumentContextMapper.hs @@ -8,6 +8,7 @@ import Wizard.Model.Document.Document import Wizard.Model.Document.DocumentContext import Wizard.Model.Questionnaire.Questionnaire import Wizard.Model.Questionnaire.QuestionnaireContent +import Wizard.Model.Questionnaire.QuestionnaireFileSimple import Wizard.Model.Report.Report import Wizard.Model.Tenant.Config.TenantConfig import Wizard.Model.User.User @@ -24,6 +25,7 @@ toDocumentContext -> QuestionnaireContent -> Maybe U.UUID -> [QuestionnaireVersionDTO] + -> [QuestionnaireFileSimple] -> KnowledgeModel -> Report -> Package @@ -33,7 +35,7 @@ toDocumentContext -> [DocumentContextUserPerm] -> [DocumentContextUserGroupPerm] -> DocumentContext -toDocumentContext doc appClientUrl qtn qtnCtn qtnVersion qtnVersionDtos km report pkg org mQtnCreatedBy mDocCreatedBy users groups = +toDocumentContext doc appClientUrl qtn qtnCtn qtnVersion qtnVersionDtos qtnFiles km report pkg org mQtnCreatedBy mDocCreatedBy users groups = DocumentContext { config = DocumentContextConfig {clientUrl = appClientUrl} , document = @@ -56,6 +58,7 @@ toDocumentContext doc appClientUrl qtn qtnCtn qtnVersion qtnVersionDtos km repor , versionUuid = qtnVersion , versions = qtnVersionDtos , projectTags = qtn.projectTags + , files = qtnFiles , createdBy = USR_Mapper.toDTO <$> mQtnCreatedBy , createdAt = qtn.createdAt , updatedAt = qtn.updatedAt diff --git a/wizard-server/src/Wizard/Service/Document/Context/DocumentContextService.hs b/wizard-server/src/Wizard/Service/Document/Context/DocumentContextService.hs index 61f955d7b..2b23cc593 100644 --- a/wizard-server/src/Wizard/Service/Document/Context/DocumentContextService.hs +++ b/wizard-server/src/Wizard/Service/Document/Context/DocumentContextService.hs @@ -13,6 +13,7 @@ import Shared.Common.Util.List import Wizard.Api.Resource.Acl.MemberDTO import Wizard.Api.Resource.Questionnaire.QuestionnairePermDTO import Wizard.Database.DAO.Questionnaire.QuestionnaireDAO +import Wizard.Database.DAO.Questionnaire.QuestionnaireFileDAO import Wizard.Database.DAO.User.UserDAO import Wizard.Model.Context.AppContext import Wizard.Model.Document.Document @@ -59,6 +60,7 @@ createDocumentContext doc = do (Just eventUuid) -> findQuestionnaireVersionUuid eventUuid qtn.versions _ -> Nothing qtnVersionDtos <- traverse enhanceQuestionnaireVersion qtn.versions + qtnFiles <- findQuestionnaireFilesByQuestionnaire doc.questionnaireUuid (users, groups) <- heSettingsToPerms qtnSettings return $ toDocumentContext @@ -68,6 +70,7 @@ createDocumentContext doc = do qtnCtn qtnVersion qtnVersionDtos + qtnFiles km report pkg diff --git a/wizard-server/src/Wizard/Service/KnowledgeModel/Compilator/Modifier/Question.hs b/wizard-server/src/Wizard/Service/KnowledgeModel/Compilator/Modifier/Question.hs index c92d82ef4..750e11b9b 100644 --- a/wizard-server/src/Wizard/Service/KnowledgeModel/Compilator/Modifier/Question.hs +++ b/wizard-server/src/Wizard/Service/KnowledgeModel/Compilator/Modifier/Question.hs @@ -95,6 +95,20 @@ instance CreateEntity AddQuestionEvent Question where , expertUuids = [] , listQuestionUuid = event.listQuestionUuid } + createEntity (AddFileQuestionEvent' event) = + FileQuestion' $ + FileQuestion + { uuid = event.entityUuid + , title = event.title + , text = event.text + , requiredPhaseUuid = event.requiredPhaseUuid + , annotations = event.annotations + , tagUuids = event.tagUuids + , referenceUuids = [] + , expertUuids = [] + , maxSize = event.maxSize + , fileTypes = event.fileTypes + } instance EditEntity EditQuestionEvent Question where editEntity event' q = @@ -105,6 +119,7 @@ instance EditEntity EditQuestionEvent Question where (EditValueQuestionEvent' event) -> applyToValueQuestion event . convertToValueQuestion $ q (EditIntegrationQuestionEvent' event) -> applyToIntegrationQuestion event . convertToIntegrationQuestion $ q (EditItemSelectQuestionEvent' event) -> applyToItemSelectQuestion event . convertToItemSelectQuestion $ q + (EditFileQuestionEvent' event) -> applyToFileQuestion event . convertToFileQuestion $ q where applyToOptionsQuestion event optionQuestion = OptionsQuestion' $ @@ -179,6 +194,19 @@ instance EditEntity EditQuestionEvent Question where , expertUuids = applyValue itemSelectQuestion.expertUuids event.expertUuids , listQuestionUuid = applyValue itemSelectQuestion.listQuestionUuid event.listQuestionUuid } + applyToFileQuestion event fileQuestion = + FileQuestion' $ + fileQuestion + { title = applyValue fileQuestion.title event.title + , text = applyValue fileQuestion.text event.text + , requiredPhaseUuid = applyValue fileQuestion.requiredPhaseUuid event.requiredPhaseUuid + , annotations = applyValue fileQuestion.annotations event.annotations + , tagUuids = applyValue fileQuestion.tagUuids event.tagUuids + , referenceUuids = applyValue fileQuestion.referenceUuids event.referenceUuids + , expertUuids = applyValue fileQuestion.expertUuids event.expertUuids + , maxSize = applyValue fileQuestion.maxSize event.maxSize + , fileTypes = applyValue fileQuestion.fileTypes event.fileTypes + } convertToOptionsQuestion :: Question -> OptionsQuestion convertToOptionsQuestion q' = @@ -189,6 +217,7 @@ convertToOptionsQuestion q' = (ValueQuestion' q) -> createQuestion q (IntegrationQuestion' q) -> createQuestion q (ItemSelectQuestion' q) -> createQuestion q + (FileQuestion' q) -> createQuestion q where createQuestion q = OptionsQuestion @@ -212,6 +241,7 @@ convertToListQuestion q' = (ValueQuestion' q) -> createQuestion q (IntegrationQuestion' q) -> createQuestion q (ItemSelectQuestion' q) -> createQuestion q + (FileQuestion' q) -> createQuestion q where createQuestion q = ListQuestion @@ -235,6 +265,7 @@ convertToMultiChoiceQuestion q' = (ValueQuestion' q) -> createQuestion q (IntegrationQuestion' q) -> createQuestion q (ItemSelectQuestion' q) -> createQuestion q + (FileQuestion' q) -> createQuestion q where createQuestion q = MultiChoiceQuestion @@ -258,6 +289,7 @@ convertToValueQuestion q' = (ValueQuestion' q) -> q (IntegrationQuestion' q) -> createQuestion q (ItemSelectQuestion' q) -> createQuestion q + (FileQuestion' q) -> createQuestion q where createQuestion q = ValueQuestion @@ -281,6 +313,7 @@ convertToIntegrationQuestion q' = (ValueQuestion' q) -> createQuestion q (IntegrationQuestion' q) -> q (ItemSelectQuestion' q) -> createQuestion q + (FileQuestion' q) -> createQuestion q where createQuestion q = IntegrationQuestion @@ -305,6 +338,7 @@ convertToItemSelectQuestion q' = (ValueQuestion' q) -> createQuestion q (IntegrationQuestion' q) -> createQuestion q (ItemSelectQuestion' q) -> q + (FileQuestion' q) -> createQuestion q where createQuestion q = ItemSelectQuestion @@ -319,6 +353,30 @@ convertToItemSelectQuestion q' = , listQuestionUuid = Nothing } +convertToFileQuestion :: Question -> FileQuestion +convertToFileQuestion (FileQuestion' q) = q +convertToFileQuestion q' = + case q' of + (OptionsQuestion' q) -> createQuestion q + (MultiChoiceQuestion' q) -> createQuestion q + (ListQuestion' q) -> createQuestion q + (ValueQuestion' q) -> createQuestion q + (ItemSelectQuestion' q) -> createQuestion q + where + createQuestion q = + FileQuestion + { uuid = q.uuid + , title = q.title + , text = q.text + , requiredPhaseUuid = q.requiredPhaseUuid + , annotations = q.annotations + , tagUuids = q.tagUuids + , referenceUuids = q.referenceUuids + , expertUuids = q.expertUuids + , maxSize = Nothing + , fileTypes = Nothing + } + updateIntegrationProps :: EditIntegrationEvent -> Question -> Question updateIntegrationProps event (IntegrationQuestion' q) = IntegrationQuestion' $ q {props = updatedProps} where diff --git a/wizard-server/src/Wizard/Service/KnowledgeModel/Squash/Event/Question.hs b/wizard-server/src/Wizard/Service/KnowledgeModel/Squash/Event/Question.hs index 32ca5bb1e..c4036ce64 100644 --- a/wizard-server/src/Wizard/Service/KnowledgeModel/Squash/Event/Question.hs +++ b/wizard-server/src/Wizard/Service/KnowledgeModel/Squash/Event/Question.hs @@ -46,6 +46,12 @@ instance SimpleEventSquash EditQuestionEvent where || isChanged (.expertUuids) event || isChanged (.referenceUuids) event || isChanged (.listQuestionUuid) event + isSimpleEventSquashApplicable (EditFileQuestionEvent' event) = + not $ + isChanged (.requiredPhaseUuid) event + || isChanged (.tagUuids) event + || isChanged (.expertUuids) event + || isChanged (.referenceUuids) event -- -------------------------------------- isReorderEventSquashApplicable previousEvent newEvent = getEntityUuid previousEvent == getEntityUuid newEvent @@ -57,6 +63,7 @@ instance SimpleEventSquash EditQuestionEvent where isTypeChanged (EditValueQuestionEvent' oldEvent) (EditValueQuestionEvent' newEvent) = False isTypeChanged (EditIntegrationQuestionEvent' oldEvent) (EditIntegrationQuestionEvent' newEvent) = False isTypeChanged (EditItemSelectQuestionEvent' oldEvent) (EditItemSelectQuestionEvent' newEvent) = False + isTypeChanged (EditFileQuestionEvent' oldEvent) (EditFileQuestionEvent' newEvent) = False isTypeChanged _ _ = True -- -------------------------------------- @@ -157,3 +164,20 @@ instance SimpleEventSquash EditQuestionEvent where , listQuestionUuid = applyValue oldEvent newEvent (.listQuestionUuid) , createdAt = oldEvent.createdAt } + simpleSquashEvent mPreviousEvent (EditFileQuestionEvent' oldEvent) (EditFileQuestionEvent' newEvent) = + EditFileQuestionEvent' $ + EditFileQuestionEvent + { uuid = newEvent.uuid + , parentUuid = newEvent.parentUuid + , entityUuid = newEvent.entityUuid + , title = applyValue oldEvent newEvent (.title) + , text = applyValue oldEvent newEvent (.text) + , requiredPhaseUuid = applyValue oldEvent newEvent (.requiredPhaseUuid) + , annotations = applyValue oldEvent newEvent (.annotations) + , tagUuids = applyValueIfSameEntity mPreviousEvent oldEvent newEvent (.tagUuids) + , expertUuids = applyValueIfSameEntity mPreviousEvent oldEvent newEvent (.expertUuids) + , referenceUuids = applyValueIfSameEntity mPreviousEvent oldEvent newEvent (.referenceUuids) + , maxSize = applyValue oldEvent newEvent (.maxSize) + , fileTypes = applyValue oldEvent newEvent (.fileTypes) + , createdAt = oldEvent.createdAt + } diff --git a/wizard-server/src/Wizard/Service/Questionnaire/Collaboration/CollaborationMapper.hs b/wizard-server/src/Wizard/Service/Questionnaire/Collaboration/CollaborationMapper.hs index 7a36e1afe..5cb695d33 100644 --- a/wizard-server/src/Wizard/Service/Questionnaire/Collaboration/CollaborationMapper.hs +++ b/wizard-server/src/Wizard/Service/Questionnaire/Collaboration/CollaborationMapper.hs @@ -4,6 +4,7 @@ import Wizard.Api.Resource.Questionnaire.Event.QuestionnaireEventDTO import Wizard.Api.Resource.Questionnaire.QuestionnaireDetailWsDTO import Wizard.Api.Resource.Websocket.QuestionnaireActionDTO import Wizard.Api.Resource.Websocket.WebsocketActionDTO +import Wizard.Model.Questionnaire.QuestionnaireFileSimple import Wizard.Model.Websocket.WebsocketMessage import Wizard.Model.Websocket.WebsocketRecord import Wizard.Util.Websocket @@ -115,3 +116,9 @@ toSetQuestionnaireMessage resWsDto record = toWebsocketMessage record $ Success_ServerActionDTO . SetQuestionnaire_ServerQuestionnaireActionDTO $ resWsDto + +toAddFileMessage :: QuestionnaireFileSimple -> WebsocketRecord -> WebsocketMessage (Success_ServerActionDTO ServerQuestionnaireActionDTO) +toAddFileMessage file record = + toWebsocketMessage record $ + Success_ServerActionDTO . AddFile_ServerQuestionnaireActionDTO $ + file diff --git a/wizard-server/src/Wizard/Service/Questionnaire/Collaboration/CollaborationService.hs b/wizard-server/src/Wizard/Service/Questionnaire/Collaboration/CollaborationService.hs index e83af4b15..abe652814 100644 --- a/wizard-server/src/Wizard/Service/Questionnaire/Collaboration/CollaborationService.hs +++ b/wizard-server/src/Wizard/Service/Questionnaire/Collaboration/CollaborationService.hs @@ -29,6 +29,7 @@ import Wizard.Localization.Messages.Public import Wizard.Model.Config.ServerConfig import Wizard.Model.Context.AppContext import Wizard.Model.Questionnaire.Questionnaire +import Wizard.Model.Questionnaire.QuestionnaireFileSimple import Wizard.Model.Questionnaire.QuestionnairePerm import Wizard.Model.Tenant.Tenant import Wizard.Model.User.OnlineUserInfo @@ -141,6 +142,27 @@ setQuestionnaire qtnUuid reqDto = do broadcast (U.toString qtnUuid) records (toSetQuestionnaireMessage reqDto) disconnectUser logWS U.nil "Informed completed" +addFile :: U.UUID -> QuestionnaireFileSimple -> AppContextM () +addFile qtnUuid reqDto = do + currentTenantUuid <- asks currentTenantUuid + tenant <- findTenantByUuid currentTenantUuid + if isJust tenant.signalBridgeUrl + then do + serverConfig <- asks serverConfig + let dto = + AKM.fromList + [ ("questionnaireUuid", A.String . U.toText $ qtnUuid) + , ("tenantUuid", A.String . U.toText $ currentTenantUuid) + , ("message", A.toJSON reqDto) + ] + invokeLambda serverConfig.signalBridge.addFileArn (BSL.toStrict . A.encode $ dto) + return () + else do + logWS U.nil "Informing other users about added file" + records <- getAllFromCache + broadcast (U.toString qtnUuid) records (toAddFileMessage reqDto) disconnectUser + logWS U.nil "Informed completed" + logOutOnlineUsersWhenQtnDramaticallyChanged :: U.UUID -> AppContextM () logOutOnlineUsersWhenQtnDramaticallyChanged qtnUuid = do currentTenantUuid <- asks currentTenantUuid diff --git a/wizard-server/src/Wizard/Service/Questionnaire/File/QuestionnaireFileAcl.hs b/wizard-server/src/Wizard/Service/Questionnaire/File/QuestionnaireFileAcl.hs new file mode 100644 index 000000000..99d8e84fc --- /dev/null +++ b/wizard-server/src/Wizard/Service/Questionnaire/File/QuestionnaireFileAcl.hs @@ -0,0 +1,18 @@ +module Wizard.Service.Questionnaire.File.QuestionnaireFileAcl where + +import qualified Data.UUID as U + +import Wizard.Database.DAO.Questionnaire.QuestionnaireDAO +import Wizard.Model.Context.AppContext +import Wizard.Model.Questionnaire.Questionnaire +import Wizard.Service.Questionnaire.QuestionnaireAcl + +checkViewPermissionToFile :: U.UUID -> AppContextM () +checkViewPermissionToFile qtnUuid = do + qtn <- findQuestionnaireByUuid qtnUuid + checkViewPermissionToQtn qtn.visibility qtn.sharing qtn.permissions + +checkEditPermissionToFile :: U.UUID -> AppContextM () +checkEditPermissionToFile qtnUuid = do + qtn <- findQuestionnaireByUuid qtnUuid + checkEditPermissionToQtn qtn.visibility qtn.sharing qtn.permissions diff --git a/wizard-server/src/Wizard/Service/Questionnaire/File/QuestionnaireFileMapper.hs b/wizard-server/src/Wizard/Service/Questionnaire/File/QuestionnaireFileMapper.hs new file mode 100644 index 000000000..55ab59648 --- /dev/null +++ b/wizard-server/src/Wizard/Service/Questionnaire/File/QuestionnaireFileMapper.hs @@ -0,0 +1,48 @@ +module Wizard.Service.Questionnaire.File.QuestionnaireFileMapper where + +import qualified Data.ByteString.Char8 as BS +import Data.Time +import qualified Data.UUID as U + +import Wizard.Api.Resource.File.FileCreateDTO +import Wizard.Api.Resource.User.UserDTO +import Wizard.Model.Questionnaire.Questionnaire +import Wizard.Model.Questionnaire.QuestionnaireFile +import Wizard.Model.Questionnaire.QuestionnaireFileList +import Wizard.Model.Questionnaire.QuestionnaireFileSimple +import qualified Wizard.Service.Questionnaire.QuestionnaireMapper as QuestionnaireMapper +import qualified Wizard.Service.User.UserMapper as UserMapper + +toList :: QuestionnaireFile -> Questionnaire -> Maybe UserDTO -> QuestionnaireFileList +toList QuestionnaireFile {..} questionnaire mCreatedBy = + QuestionnaireFileList + { uuid = uuid + , fileName = fileName + , contentType = contentType + , fileSize = fileSize + , questionnaire = QuestionnaireMapper.toSimple questionnaire + , createdBy = fmap UserMapper.toSuggestionDTO' mCreatedBy + , createdAt = createdAt + } + +toSimple :: QuestionnaireFile -> QuestionnaireFileSimple +toSimple QuestionnaireFile {..} = + QuestionnaireFileSimple + { uuid = uuid + , fileName = fileName + , contentType = contentType + , fileSize = fileSize + } + +fromFileCreateDTO :: FileCreateDTO -> U.UUID -> U.UUID -> Maybe UserDTO -> U.UUID -> UTCTime -> QuestionnaireFile +fromFileCreateDTO reqDto uuid qtnUuid mCreatedBy tenantUuid now = + QuestionnaireFile + { uuid = uuid + , fileName = reqDto.fileName + , contentType = reqDto.contentType + , fileSize = fromIntegral . BS.length $ reqDto.content + , questionnaireUuid = qtnUuid + , createdBy = fmap (.uuid) mCreatedBy + , tenantUuid = tenantUuid + , createdAt = now + } diff --git a/wizard-server/src/Wizard/Service/Questionnaire/File/QuestionnaireFileService.hs b/wizard-server/src/Wizard/Service/Questionnaire/File/QuestionnaireFileService.hs new file mode 100644 index 000000000..49f468823 --- /dev/null +++ b/wizard-server/src/Wizard/Service/Questionnaire/File/QuestionnaireFileService.hs @@ -0,0 +1,86 @@ +module Wizard.Service.Questionnaire.File.QuestionnaireFileService where + +import Control.Monad.Reader (asks, liftIO) +import qualified Data.ByteString.Lazy.Char8 as BSL +import Data.Foldable (traverse_) +import Data.Time +import qualified Data.UUID as U + +import Shared.Common.Model.Common.Page +import Shared.Common.Model.Common.Pageable +import Shared.Common.Model.Common.Sort +import Shared.Common.Service.Acl.AclService +import Shared.Common.Util.Uuid +import Wizard.Api.Resource.File.FileCreateDTO +import Wizard.Api.Resource.TemporaryFile.TemporaryFileDTO +import Wizard.Constant.Acl +import Wizard.Database.DAO.Common +import Wizard.Database.DAO.Questionnaire.QuestionnaireDAO +import Wizard.Database.DAO.Questionnaire.QuestionnaireFileDAO +import Wizard.Model.Context.AppContext +import Wizard.Model.Questionnaire.Questionnaire +import Wizard.Model.Questionnaire.QuestionnaireFile +import Wizard.Model.Questionnaire.QuestionnaireFileList +import Wizard.Model.Questionnaire.QuestionnaireFileSimple +import Wizard.S3.Questionnaire.QuestionnaireFileS3 +import Wizard.Service.Questionnaire.Collaboration.CollaborationService +import Wizard.Service.Questionnaire.File.QuestionnaireFileAcl +import Wizard.Service.Questionnaire.File.QuestionnaireFileMapper +import Wizard.Service.Questionnaire.QuestionnaireAcl +import qualified Wizard.Service.TemporaryFile.TemporaryFileMapper as TemporaryFileMapper +import Wizard.Service.TemporaryFile.TemporaryFileService +import Wizard.Service.Tenant.Limit.LimitService + +getQuestionnaireFilesPage :: Maybe String -> Maybe U.UUID -> Pageable -> [Sort] -> AppContextM (Page QuestionnaireFileList) +getQuestionnaireFilesPage mQuery mQtnUuid pageable sort = do + case mQtnUuid of + Just qtnUuid -> do + qtn <- findQuestionnaireByUuid qtnUuid + checkViewPermissionToQtn qtn.visibility qtn.sharing qtn.permissions + Nothing -> checkPermission _QTN_FILE_PERM + findQuestionnaireFilesPage mQuery mQtnUuid pageable sort + +createQuestionnaireFile :: U.UUID -> FileCreateDTO -> AppContextM QuestionnaireFileList +createQuestionnaireFile qtnUuid reqDto = + runInTransaction $ do + qtn <- findQuestionnaireByUuid qtnUuid + checkViewPermissionToQtn qtn.visibility qtn.sharing qtn.permissions + uuid <- liftIO generateUuid + mCurrentUser <- asks currentUser + tenantUuid <- asks currentTenantUuid + now <- liftIO getCurrentTime + let qtnFile = fromFileCreateDTO reqDto uuid qtnUuid mCurrentUser tenantUuid now + checkStorageSize qtnFile.fileSize + insertQuestionnaireFile qtnFile + putFile qtnUuid uuid reqDto.contentType reqDto.content + addFile qtnUuid (toSimple qtnFile) + return $ toList qtnFile qtn mCurrentUser + +downloadQuestionnaireFile :: U.UUID -> U.UUID -> AppContextM TemporaryFileDTO +downloadQuestionnaireFile qtnUuid fileUuid = do + runInTransaction $ do + qtnFile <- findQuestionnaireFileByUuid fileUuid + checkViewPermissionToFile qtnUuid + content <- retrieveFile qtnUuid fileUuid + url <- createTemporaryFile qtnFile.fileName "application/octet-stream" (BSL.fromStrict content) + return $ TemporaryFileMapper.toDTO url qtnFile.contentType + +deleteQuestionnaireFilesByQuestionnaireUuid :: U.UUID -> AppContextM () +deleteQuestionnaireFilesByQuestionnaireUuid qtnUuid = do + runInTransaction $ do + files <- findQuestionnaireFilesByQuestionnaire qtnUuid + checkEditPermissionToFile qtnUuid + traverse_ + ( \file -> do + deleteQuestionnaireFileByUuid file.uuid + removeFile qtnUuid file.uuid + ) + files + +deleteQuestionnaireFile :: U.UUID -> U.UUID -> AppContextM () +deleteQuestionnaireFile qtnUuid fileUuid = do + runInTransaction $ do + _ <- findQuestionnaireFileByUuid fileUuid + checkEditPermissionToFile qtnUuid + deleteQuestionnaireFileByUuid fileUuid + removeFile qtnUuid fileUuid diff --git a/wizard-server/src/Wizard/Service/Questionnaire/QuestionnaireMapper.hs b/wizard-server/src/Wizard/Service/Questionnaire/QuestionnaireMapper.hs index 2ce1e547d..3e92f6869 100644 --- a/wizard-server/src/Wizard/Service/Questionnaire/QuestionnaireMapper.hs +++ b/wizard-server/src/Wizard/Service/Questionnaire/QuestionnaireMapper.hs @@ -25,6 +25,7 @@ import Wizard.Model.DocumentTemplate.DocumentTemplateState import Wizard.Model.Questionnaire.Questionnaire import Wizard.Model.Questionnaire.QuestionnaireCommentList import Wizard.Model.Questionnaire.QuestionnaireContent +import Wizard.Model.Questionnaire.QuestionnaireDetail import Wizard.Model.Questionnaire.QuestionnaireDetailQuestionnaire import Wizard.Model.Questionnaire.QuestionnaireEvent import Wizard.Model.Questionnaire.QuestionnaireList @@ -109,17 +110,19 @@ toDetailQuestionnaire qtn migrationUuid permissions questionnaireActionsAvailabl , migrationUuid = migrationUuid , permissions = permissions , events = qtn.events + , files = [] , questionnaireActionsAvailable = questionnaireActionsAvailable , questionnaireImportersAvailable = questionnaireImportersAvailable } -toDetailDTO :: QuestionnaireDetailQuestionnaire -> QuestionnaireDetailDTO -toDetailDTO QuestionnaireDetailQuestionnaire {..} = +toDetailDTO :: QuestionnaireDetail -> QuestionnaireDetailDTO +toDetailDTO QuestionnaireDetail {..} = QuestionnaireDetailDTO {..} toDetailQuestionnaireDTO :: QuestionnaireDetailQuestionnaire -> M.Map String (M.Map U.UUID Int) -> M.Map String (M.Map U.UUID Int) -> KnowledgeModel -> QuestionnaireContent -> QuestionnaireDetailQuestionnaireDTO toDetailQuestionnaireDTO QuestionnaireDetailQuestionnaire {..} unresolvedCommentCounts resolvedCommentCounts knowledgeModel QuestionnaireContent {..} = - QuestionnaireDetailQuestionnaireDTO {..} + let fileCount = length files + in QuestionnaireDetailQuestionnaireDTO {..} toDetailWsDTO :: Questionnaire -> Maybe DocumentTemplate -> Maybe DocumentTemplateFormat -> [QuestionnairePermDTO] -> QuestionnaireDetailWsDTO toDetailWsDTO qtn mTemplate mFormat qtnPerms = diff --git a/wizard-server/src/Wizard/Service/Questionnaire/QuestionnaireService.hs b/wizard-server/src/Wizard/Service/Questionnaire/QuestionnaireService.hs index 86856bd1d..df851175f 100644 --- a/wizard-server/src/Wizard/Service/Questionnaire/QuestionnaireService.hs +++ b/wizard-server/src/Wizard/Service/Questionnaire/QuestionnaireService.hs @@ -47,6 +47,7 @@ import Wizard.Model.Document.Document import Wizard.Model.Questionnaire.Questionnaire import Wizard.Model.Questionnaire.QuestionnaireAclHelpers import Wizard.Model.Questionnaire.QuestionnaireComment +import Wizard.Model.Questionnaire.QuestionnaireDetail import Wizard.Model.Questionnaire.QuestionnaireDetailPreview import Wizard.Model.Questionnaire.QuestionnaireDetailQuestionnaire import Wizard.Model.Questionnaire.QuestionnaireDetailSettings @@ -60,6 +61,7 @@ import Wizard.Service.Package.PackageService import Wizard.Service.Questionnaire.Collaboration.CollaborationService import Wizard.Service.Questionnaire.Comment.QuestionnaireCommentService import Wizard.Service.Questionnaire.Compiler.CompilerService +import Wizard.Service.Questionnaire.File.QuestionnaireFileService import Wizard.Service.Questionnaire.QuestionnaireAcl import Wizard.Service.Questionnaire.QuestionnaireAudit import Wizard.Service.Questionnaire.QuestionnaireMapper @@ -249,7 +251,7 @@ getQuestionnaireDetailByUuid qtnUuid = do getQuestionnaireDetailQuestionnaireById :: U.UUID -> AppContextM QuestionnaireDetailQuestionnaireDTO getQuestionnaireDetailQuestionnaireById qtnUuid = do - qtn <- findQuestionnaireDetail qtnUuid + qtn <- findQuestionnaireDetailQuestionnaire qtnUuid checkViewPermissionToQtn qtn.visibility qtn.sharing qtn.permissions editor <- catchError (hasEditPermissionToQtn qtn.visibility qtn.sharing qtn.permissions) (\_ -> return False) commenter <- catchError (hasCommentPermissionToQtn qtn.visibility qtn.sharing qtn.permissions) (\_ -> return False) @@ -379,6 +381,7 @@ deleteQuestionnaire qtnUuid shouldValidatePermission = removeDocumentContent d.uuid ) documents + deleteQuestionnaireFilesByQuestionnaireUuid qtnUuid deleteQuestionnairePermsFiltered [("questionnaire_uuid", U.toString qtnUuid)] deleteQuestionnaireByUuid qtnUuid logOutOnlineUsersWhenQtnDramaticallyChanged qtnUuid diff --git a/wizard-server/src/Wizard/Service/Report/Evaluator/Indication.hs b/wizard-server/src/Wizard/Service/Report/Evaluator/Indication.hs index 910850d3c..5781a593f 100644 --- a/wizard-server/src/Wizard/Service/Report/Evaluator/Indication.hs +++ b/wizard-server/src/Wizard/Service/Report/Evaluator/Indication.hs @@ -56,6 +56,7 @@ evaluateQuestion found notFound mQtnPhase km replies path q' = ItemSelectQuestion' q -> rFound OptionsQuestion' q -> rFound + evaluateOptionsQuestion q found notFound mQtnPhase km replies currentPath ListQuestion' q -> evaluateListQuestion found notFound mQtnPhase km replies currentPath q + FileQuestion' q -> rFound where rFound = isRequiredNow km.phaseUuids (getRequiredPhaseUuid q') mQtnPhase found diff --git a/wizard-server/src/Wizard/Service/Report/Evaluator/Metric.hs b/wizard-server/src/Wizard/Service/Report/Evaluator/Metric.hs index 166a9dd81..7028b465d 100644 --- a/wizard-server/src/Wizard/Service/Report/Evaluator/Metric.hs +++ b/wizard-server/src/Wizard/Service/Report/Evaluator/Metric.hs @@ -66,6 +66,7 @@ evaluateQuestion km replies path q' = ItemSelectQuestion' q -> [] OptionsQuestion' q -> evaluateOptionsQuestion q km replies currentPath ListQuestion' q -> evaluateListQuestion km replies currentPath q + FileQuestion' q -> [] evaluateOptionsQuestion :: OptionsQuestion -> KnowledgeModel -> M.Map String Reply -> String -> [MetricMeasure] evaluateOptionsQuestion q km replies path = diff --git a/wizard-server/src/Wizard/Service/Report/ReportMapper.hs b/wizard-server/src/Wizard/Service/Report/ReportMapper.hs index 30ea5f776..2cacad4ca 100644 --- a/wizard-server/src/Wizard/Service/Report/ReportMapper.hs +++ b/wizard-server/src/Wizard/Service/Report/ReportMapper.hs @@ -15,6 +15,7 @@ toDTO qtn report = , isTemplate = qtn.isTemplate , permissions = qtn.permissions , migrationUuid = qtn.migrationUuid + , fileCount = qtn.fileCount , totalReport = report.totalReport , chapters = report.chapters , chapterReports = report.chapterReports diff --git a/wizard-server/src/Wizard/Service/User/UserMapper.hs b/wizard-server/src/Wizard/Service/User/UserMapper.hs index abcdde8cb..8c05133ab 100644 --- a/wizard-server/src/Wizard/Service/User/UserMapper.hs +++ b/wizard-server/src/Wizard/Service/User/UserMapper.hs @@ -76,7 +76,17 @@ toSuggestionDTO user = { uuid = user.uuid , firstName = user.firstName , lastName = user.lastName - , gravatarHash = createGravatarHash $ user.email + , gravatarHash = createGravatarHash user.email + , imageUrl = user.imageUrl + } + +toSuggestionDTO' :: UserDTO -> UserSuggestionDTO +toSuggestionDTO' user = + UserSuggestionDTO + { uuid = user.uuid + , firstName = user.firstName + , lastName = user.lastName + , gravatarHash = createGravatarHash user.email , imageUrl = user.imageUrl } diff --git a/wizard-server/test/Wizard/Specs/API/Questionnaire/Detail_GET.hs b/wizard-server/test/Wizard/Specs/API/Questionnaire/Detail_GET.hs index 663989537..cfe5e9889 100644 --- a/wizard-server/test/Wizard/Specs/API/Questionnaire/Detail_GET.hs +++ b/wizard-server/test/Wizard/Specs/API/Questionnaire/Detail_GET.hs @@ -128,6 +128,7 @@ create_test_200 title appContext qtn authHeader permissions = , isTemplate = qtn.isTemplate , migrationUuid = Nothing , permissions = permissions + , fileCount = 0 } let expBody = encode expDto -- WHEN: Call API diff --git a/wizard-server/test/Wizard/Specs/API/Questionnaire/Detail_Preview_GET.hs b/wizard-server/test/Wizard/Specs/API/Questionnaire/Detail_Preview_GET.hs index 4b32d7c6a..4c7345f42 100644 --- a/wizard-server/test/Wizard/Specs/API/Questionnaire/Detail_Preview_GET.hs +++ b/wizard-server/test/Wizard/Specs/API/Questionnaire/Detail_Preview_GET.hs @@ -132,6 +132,7 @@ create_test_200 title appContext qtn authHeader permissions = , permissions = permissions , documentTemplateId = qtn.documentTemplateId , format = Just . SDTM.toFormatDTO $ formatJson + , fileCount = 0 } let expBody = encode expDto -- WHEN: Call API diff --git a/wizard-server/test/Wizard/Specs/API/Questionnaire/Detail_Questionnaire_GET.hs b/wizard-server/test/Wizard/Specs/API/Questionnaire/Detail_Questionnaire_GET.hs index 043f59b8c..5c755e909 100644 --- a/wizard-server/test/Wizard/Specs/API/Questionnaire/Detail_Questionnaire_GET.hs +++ b/wizard-server/test/Wizard/Specs/API/Questionnaire/Detail_Questionnaire_GET.hs @@ -160,10 +160,12 @@ create_test_200 title appContext qtn qtnCtn showComments authHeader permissions , phaseUuid = qtnCtn.phaseUuid , migrationUuid = Nothing , permissions = permissions + , files = [] , unresolvedCommentCounts = unresolvedCommentCounts , resolvedCommentCounts = M.empty , questionnaireActionsAvailable = 0 , questionnaireImportersAvailable = 0 + , fileCount = 0 } let expBody = encode expDto -- WHEN: Call API diff --git a/wizard-server/test/Wizard/Specs/API/Questionnaire/Detail_Settings_GET.hs b/wizard-server/test/Wizard/Specs/API/Questionnaire/Detail_Settings_GET.hs index 3bce64f71..235ed84ed 100644 --- a/wizard-server/test/Wizard/Specs/API/Questionnaire/Detail_Settings_GET.hs +++ b/wizard-server/test/Wizard/Specs/API/Questionnaire/Detail_Settings_GET.hs @@ -147,6 +147,7 @@ create_test_200 title appContext qtn authHeader permissions = , documentTemplatePhase = Just wizardDocumentTemplate.phase , formatUuid = Just formatJson.uuid , selectedQuestionTagUuids = qtn.selectedQuestionTagUuids + , fileCount = 0 } let expBody = encode expDto -- WHEN: Call API diff --git a/wizard-server/test/Wizard/Specs/Service/KnowledgeModel/Compilator/CompilatorSpec.hs b/wizard-server/test/Wizard/Specs/Service/KnowledgeModel/Compilator/CompilatorSpec.hs index f88e0ebe7..0515406f0 100644 --- a/wizard-server/test/Wizard/Specs/Service/KnowledgeModel/Compilator/CompilatorSpec.hs +++ b/wizard-server/test/Wizard/Specs/Service/KnowledgeModel/Compilator/CompilatorSpec.hs @@ -68,7 +68,7 @@ compilatorSpec = { entities = km1.entities { chapters = toMap [chapter2, chapter3] - , questions = toMap [question3', question9', question10', question11', question12', question13'] + , questions = toMap [question3', question9', question10', question11', question12', question13', question14'] , answers = toMap [q3_answerNo, q3_answerYes] , experts = toMap [] , references = toMap [] @@ -97,6 +97,7 @@ compilatorSpec = , question11' , question12' , question13' + , question14' ] } } @@ -119,6 +120,7 @@ compilatorSpec = , question11' , question12' , question13' + , question14' ] } } @@ -151,6 +153,7 @@ compilatorSpec = , question11' , question12' , question13' + , question14' ] , answers = toMap @@ -224,6 +227,7 @@ compilatorSpec = , question11' , question12' , question13' + , question14' ] , answers = toMap [q2_answerNo, q3_answerNo, q3_answerYes] } @@ -305,6 +309,7 @@ compilatorSpec = , question11' , question12' , question13' + , question14' ] } } @@ -625,6 +630,7 @@ compilatorSpec = , AddChoiceEvent' a_km1_ch3_q11_cho2 , AddQuestionEvent' a_km1_ch3_q12' , AddQuestionEvent' a_km1_ch3_q13' + , AddQuestionEvent' a_km1_ch3_q14' ] let (Right computed) = compile Nothing events let expected = km1WithQ4 diff --git a/wizard-server/test/Wizard/Specs/Service/KnowledgeModel/KnowledgeModelFilterSpec.hs b/wizard-server/test/Wizard/Specs/Service/KnowledgeModel/KnowledgeModelFilterSpec.hs index 2991ae413..e1c7c99fa 100644 --- a/wizard-server/test/Wizard/Specs/Service/KnowledgeModel/KnowledgeModelFilterSpec.hs +++ b/wizard-server/test/Wizard/Specs/Service/KnowledgeModel/KnowledgeModelFilterSpec.hs @@ -75,6 +75,7 @@ knowledgeModelFilterSpec = , question11' , question12' , question13' + , question14' ] , answers = toMap [q2_answerNo, q2_answerYes, q2_aYes_fuq1_answerNo, q2_aYes_fuq1_answerYes] , references = toMap [km1_ch1_q2_r1', km1_ch1_q2_r2'] diff --git a/wizard-server/test/Wizard/TestMigration.hs b/wizard-server/test/Wizard/TestMigration.hs index b1dd6d9c7..34413fec6 100644 --- a/wizard-server/test/Wizard/TestMigration.hs +++ b/wizard-server/test/Wizard/TestMigration.hs @@ -20,6 +20,7 @@ import qualified Wizard.Database.DAO.Migration.Questionnaire.MigratorDAO as QTN_ import Wizard.Database.DAO.Questionnaire.QuestionnaireCommentDAO import Wizard.Database.DAO.Questionnaire.QuestionnaireCommentThreadDAO import Wizard.Database.DAO.Questionnaire.QuestionnaireDAO +import Wizard.Database.DAO.Questionnaire.QuestionnaireFileDAO import Wizard.Database.DAO.Questionnaire.QuestionnairePermDAO import Wizard.Database.DAO.QuestionnaireAction.QuestionnaireActionDAO import Wizard.Database.DAO.QuestionnaireImporter.QuestionnaireImporterDAO @@ -151,6 +152,7 @@ resetDB appContext = do runInContext deleteBranches appContext runInContext deleteDocuments appContext runInContext deleteDrafts appContext + runInContext deleteQuestionnaireFiles appContext runInContext deleteQuestionnaireComments appContext runInContext deleteQuestionnaireCommentThreads appContext runInContext deleteQuestionnairePerms appContext