digitallyinduced / ihp

🔥 The fastest way to build type safe web apps. IHP is a new batteries-included web framework optimized for longterm productivity and programmer happiness
https://ihp.digitallyinduced.com/
MIT License
4.94k stars 197 forks source link

Runtime error from use of non gui fields in views #677

Open michaelfliegner opened 3 years ago

michaelfliegner commented 3 years ago

To reproduce: 1. -- Your database schema. Use the Schema Designer at http://localhost:8001/ to add some tables. CREATE TABLE workflows ( id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL, progress JSONB NOT NULL );

2. Generate Controller Workflows and start server

Error message:

[16 of 18] Compiling Web.Controller.Workflows ( Web/Controller/Workflows.hs, interpreted )

Failed, 15 modules loaded.
Web/Controller/Workflows.hs:29:16: error:
    • Could not deduce (ParamReader Value)
        arising from a use of ‘buildWorkflow’
      from the context: (?context::ControllerContext,
                         ?modelContext::ModelContext, ?theAction::WorkflowsController)
        bound by the type signature for:
                   action :: (?context::ControllerContext,
                              ?modelContext::ModelContext, ?theAction::WorkflowsController) =>
                             WorkflowsController -> IO ()
        at Web/Controller/Workflows.hs:10:5-10
    • In the second argument of ‘(|>)’, namely ‘buildWorkflow’
      In the first argument of ‘(|>)’, namely ‘workflow |> buildWorkflow’
      In a stmt of a 'do' block:
        workflow |> buildWorkflow
          |>
            ifValid
              \case
                Left workflow -> render EditView {..}
                Right workflow
                  -> do workflow <- workflow |> updateRecord
                        setSuccessMessage "Workflow updated"
                        ....
   |
29 |             |> buildWorkflow``
fegu commented 3 years ago

This type was added to support JSONB in Postgres, but wasn't really intended for use in GUI forms. It would definitely be better if it worked, though.

michaelfliegner commented 3 years ago

There is a deeper issue underneath: IHP's philosophy seems to be to always have a running system. Which makes it so appealing for beginners and that is a great feature. Maybe due to this approach, IHP's codegenerator is a tad simplistic in that it implies, that fields are generally intended for use in GUI forms.

For a more principled approach there should be metadata

fegu commented 3 years ago

Definitely. We should make it work as a text input field accepting JSON. I can look into it.

michaelfliegner commented 3 years ago

Hey! A text field is not necessary. It's just that the build functions without corresponding ParamReaders are a bottleneck for passing data between New/Create or Edit/Update-functions. And we don't want setSession/getSession pairs when the respective param values are already request parameters, do we?

I built a workaround, like this

buildWorkflow :: (ParamReader fieldType1, ParamReader fieldType2, ParamReader fieldType3, ParamReader fieldType4, HasField "meta" t2 MetaBag, SetField "historyType" t2 fieldType2, SetField "meta" t2 MetaBag, SetField "progress" t2 value, SetField "refuser" t2 fieldType1, SetField "validfrom" t2 fieldType4, SetField "workflowType" t2 fieldType3, FromJSON value, ?context::ControllerContext) => t2 -> t2
buildWorkflow workflow = workflow
    |> fill @["refuser","historyType","workflowType","validfrom"] |> set #progress val
        where val =fromJust $ decode $ fromStrict $ param @Web.Controller.Prelude.ByteString "progress"

but JSONB-ParamReader instance would be nicer :-)