diff --git a/.editorconfig b/.editorconfig index 41c679b7..c23f2291 100644 --- a/.editorconfig +++ b/.editorconfig @@ -6,7 +6,7 @@ insert_final_newline = true trim_trailing_whitespace = true indent_style = space indent_size = 2 -max_line_length = 120 +max_line_length = 130 [**.{yml,yaml,md,tex,txt}] max_line_length = 160 diff --git a/.github/actions/spelling/expect.txt b/.github/actions/spelling/expect.txt index 4a735744..393a65bc 100644 --- a/.github/actions/spelling/expect.txt +++ b/.github/actions/spelling/expect.txt @@ -13,6 +13,7 @@ hasdata img lindex lucius +optgroup RWS syb subdirs diff --git a/flex-tasks/src/FlexTask/Generic/Form.hs b/flex-tasks/src/FlexTask/Generic/Form.hs index 6196b3db..397d3d98 100644 --- a/flex-tasks/src/FlexTask/Generic/Form.hs +++ b/flex-tasks/src/FlexTask/Generic/Form.hs @@ -44,6 +44,7 @@ module FlexTask.Generic.Form ( , formifyInstanceBasicField , formifyInstanceOptionalField , formifyInstanceSingleChoice + , formifyInstanceOptionalSingleChoice , formifyInstanceMultiChoice ) where diff --git a/flex-tasks/src/FlexTask/Generic/FormInternal.hs b/flex-tasks/src/FlexTask/Generic/FormInternal.hs index a08d4f12..99176013 100644 --- a/flex-tasks/src/FlexTask/Generic/FormInternal.hs +++ b/flex-tasks/src/FlexTask/Generic/FormInternal.hs @@ -34,7 +34,6 @@ import Yesod ( multiSelectField, optionsPairs, renderMessage, - selectField, textareaField, textField, ) @@ -45,6 +44,7 @@ import FlexTask.Widgets , radioField , joinWidgets , renderForm + , selectField ) import FlexTask.YesodConfig (FlexForm(..), Handler, Rendered, Widget) @@ -208,6 +208,9 @@ Use if both of the following is true: Choose one + One @@ -765,6 +771,9 @@ that cannot use a bodyless `Formify` instance. Choose one + <None> + + + + + + +... + + +>>> printWidget "en" $ formify (Nothing @(Maybe MyType)) [[dropdownEnum "Choose one or abstain" (showToUniversalLabel @MyType)]] +
+... + + +... +
+-} +formifyInstanceOptionalSingleChoice + :: (Bounded a, Enum a, Eq a) + => Maybe (Maybe a) + -> [[FieldInfo]] + -> ([[FieldInfo]], Rendered [[Widget]]) +formifyInstanceOptionalSingleChoice = renderNextOptionalSingleChoiceField zipWithEnum + renderNextSingleChoiceField :: Eq a => ([SomeMessage FlexForm] -> [(SomeMessage FlexForm, a)]) @@ -796,7 +874,7 @@ renderNextSingleChoiceField pairsWith = (\case ChoicesDropdown fs opts -> ( fs - , areq $ selectField $ withOptions opts + , areq $ selectField True $ withOptions opts ) ChoicesButtons align fs opts -> ( fs @@ -809,6 +887,30 @@ renderNextSingleChoiceField pairsWith = ) where withOptions = optionsPairs . pairsWith +renderNextOptionalSingleChoiceField + :: Eq a + => ([SomeMessage FlexForm] -> [(SomeMessage FlexForm, a)]) + -> Maybe (Maybe a) + -> [[FieldInfo]] + -> ([[FieldInfo]], Rendered [[Widget]]) +renderNextOptionalSingleChoiceField pairsWith = + renderNextField + (\case + ChoicesDropdown fs opts -> + ( fs + , aopt $ selectField False $ withOptions opts + ) + ChoicesButtons align fs opts -> + ( fs + , aopt $ case align of + Vertical -> radioField True + Horizontal -> radioField False + $ withOptions opts + ) + _ -> error "Incorrect FieldInfo for an optional single choice field! Use one of the 'buttons' or 'dropdown' functions." + ) + where withOptions = optionsPairs . pairsWith + renderNextMultipleChoiceField :: Eq a => ([SomeMessage FlexForm] -> [(SomeMessage FlexForm, a)]) diff --git a/flex-tasks/src/FlexTask/Generic/ParseInternal.hs b/flex-tasks/src/FlexTask/Generic/ParseInternal.hs index ef08704a..d7861c7f 100644 --- a/flex-tasks/src/FlexTask/Generic/ParseInternal.hs +++ b/flex-tasks/src/FlexTask/Generic/ParseInternal.hs @@ -72,7 +72,6 @@ import FlexTask.Generic.FormInternal , SingleInputList(..) , multipleChoiceAnswer , singleChoiceAnswer - , singleChoiceEmpty ) @@ -233,7 +232,7 @@ instance Parse a => Parse (Maybe a) where instance Parse SingleChoiceSelection where - formParser = maybe singleChoiceEmpty singleChoiceAnswer <$> formParser + formParser = singleChoiceAnswer <$> formParser instance Parse MultipleChoiceSelection where @@ -414,7 +413,7 @@ the input form is "infallible" since only constructed from String text fields, s >>> import Control.OutputCapable.Blocks.Debug (run) >>> run German $ parseInfallibly (formParser @SingleChoiceSelection) $ asSubmission [["1"]] -Just (SingleChoiceSelection {getAnswer = Just 1}) +Just (SingleChoiceSelection {getAnswer = 1}) >>> run English $ parseInfallibly (formParser @(SingleInputList Double)) $ asSubmission [["Wrong input"]] *** Exception: The impossible happened: (line 1, column 3): diff --git a/flex-tasks/src/FlexTask/Widgets.hs b/flex-tasks/src/FlexTask/Widgets.hs index bd10a8bd..5f634be1 100644 --- a/flex-tasks/src/FlexTask/Widgets.hs +++ b/flex-tasks/src/FlexTask/Widgets.hs @@ -60,13 +60,32 @@ joinWidgets = mapM_ (insertDiv . sequence_) radioField :: Eq a => Bool -> Handler (OptionList a) -> Field Handler a -radioField isVertical = selectFieldHelper outside (\_ _ _ -> pure ()) inside Nothing +radioField isVertical = selectFieldHelper outside onOpt inside Nothing where outside theId _name _attrs inside' = toWidget horizontalRBStyle >> [whamlet| $newline never
^{inside'} +|] + onOpt theId name isSel = nothingFun theId [whamlet| +$newline never + +|] + nothingFun _ optionWidget = + let emptyRadio = [whamlet| +$newline never +