{-# language OverloadedStrings #-}
{-# language TypeOperators #-}
module FlexTask.FormUtil
(
($$>)
, addCss
, addJs
, addCssAndJs
, applyToWidget
, addAttribute
, addAttributes
, addCssClass
, addNameAndCssClass
, readOnly
, universalLabel
, showToUniversalLabel
, newFlexId
, newFlexName
, repeatFlexName
, printWidget
) where
import Data.Containers.ListUtils (nubOrd)
import Data.List.Extra (isInfixOf, isPrefixOf, trimEnd, splitOn)
import Data.String (fromString)
import Data.Text (Text, pack)
import Data.Tuple.Extra (second)
import Text.Cassius (Css)
import Text.Julius (Javascript)
import Yesod
import Yesod.Core.Types (RY)
import qualified Control.Monad.Trans.RWS as RWS (get)
import qualified Data.Map as M (lookup)
import qualified Data.Text as T (replace)
import FlexTask.ConvertForm (getFormData)
import FlexTask.YesodConfig (
FlexForm(..),
Handler,
Rendered,
Rendered',
Widget,
)
infixr 0 $$>
($$>)
:: (Monad w, Monad m)
=> Rendered' m (w a)
-> Rendered' m (w b)
-> Rendered' m (w b)
Rendered' m (w a)
f1 $$> :: forall (w :: * -> *) (m :: * -> *) a b.
(Monad w, Monad m) =>
Rendered' m (w a) -> Rendered' m (w b) -> Rendered' m (w b)
$$> Rendered' m (w b)
f2 = do
RWST
(Maybe (Env, FileEnv), FlexForm, [Lang])
Enctype
Ints
Handler
([[Lang]], w a)
res1 <- Rendered' m (w a)
m (RWST
(Maybe (Env, FileEnv), FlexForm, [Lang])
Enctype
Ints
Handler
([[Lang]], w a))
f1
RWST
(Maybe (Env, FileEnv), FlexForm, [Lang])
Enctype
Ints
Handler
([[Lang]], w b)
res2 <- Rendered' m (w b)
m (RWST
(Maybe (Env, FileEnv), FlexForm, [Lang])
Enctype
Ints
Handler
([[Lang]], w b))
f2
RWST
(Maybe (Env, FileEnv), FlexForm, [Lang])
Enctype
Ints
Handler
([[Lang]], w b)
-> m (RWST
(Maybe (Env, FileEnv), FlexForm, [Lang])
Enctype
Ints
Handler
([[Lang]], w b))
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (RWST
(Maybe (Env, FileEnv), FlexForm, [Lang])
Enctype
Ints
Handler
([[Lang]], w b)
-> m (RWST
(Maybe (Env, FileEnv), FlexForm, [Lang])
Enctype
Ints
Handler
([[Lang]], w b)))
-> RWST
(Maybe (Env, FileEnv), FlexForm, [Lang])
Enctype
Ints
Handler
([[Lang]], w b)
-> m (RWST
(Maybe (Env, FileEnv), FlexForm, [Lang])
Enctype
Ints
Handler
([[Lang]], w b))
forall a b. (a -> b) -> a -> b
$ do
([[Lang]]
names1,w a
wid1) <- RWST
(Maybe (Env, FileEnv), FlexForm, [Lang])
Enctype
Ints
Handler
([[Lang]], w a)
res1
([[Lang]]
names2,w b
wid2) <- RWST
(Maybe (Env, FileEnv), FlexForm, [Lang])
Enctype
Ints
Handler
([[Lang]], w b)
res2
([[Lang]], w b)
-> RWST
(Maybe (Env, FileEnv), FlexForm, [Lang])
Enctype
Ints
Handler
([[Lang]], w b)
forall a.
a
-> RWST
(Maybe (Env, FileEnv), FlexForm, [Lang]) Enctype Ints Handler a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([[Lang]] -> [[Lang]]
forall a. Ord a => [a] -> [a]
nubOrd ([[Lang]] -> [[Lang]]) -> [[Lang]] -> [[Lang]]
forall a b. (a -> b) -> a -> b
$ [[Lang]]
names1 [[Lang]] -> [[Lang]] -> [[Lang]]
forall a. [a] -> [a] -> [a]
++ [[Lang]]
names2, w a
wid1 w a -> w b -> w b
forall a b. w a -> w b -> w b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> w b
wid2)
applyToWidget :: Functor m => (w -> w') -> Rendered' m w -> Rendered' m w'
applyToWidget :: forall (m :: * -> *) w w'.
Functor m =>
(w -> w') -> Rendered' m w -> Rendered' m w'
applyToWidget w -> w'
f Rendered' m w
form = (([[Lang]], w) -> ([[Lang]], w'))
-> RWST
(Maybe (Env, FileEnv), FlexForm, [Lang])
Enctype
Ints
Handler
([[Lang]], w)
-> RWST
(Maybe (Env, FileEnv), FlexForm, [Lang])
Enctype
Ints
Handler
([[Lang]], w')
forall a b.
(a -> b)
-> RWST
(Maybe (Env, FileEnv), FlexForm, [Lang]) Enctype Ints Handler a
-> RWST
(Maybe (Env, FileEnv), FlexForm, [Lang]) Enctype Ints Handler b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((w -> w') -> ([[Lang]], w) -> ([[Lang]], w')
forall b b' a. (b -> b') -> (a, b) -> (a, b')
second w -> w'
f) (RWST
(Maybe (Env, FileEnv), FlexForm, [Lang])
Enctype
Ints
Handler
([[Lang]], w)
-> RWST
(Maybe (Env, FileEnv), FlexForm, [Lang])
Enctype
Ints
Handler
([[Lang]], w'))
-> m (RWST
(Maybe (Env, FileEnv), FlexForm, [Lang])
Enctype
Ints
Handler
([[Lang]], w))
-> m (RWST
(Maybe (Env, FileEnv), FlexForm, [Lang])
Enctype
Ints
Handler
([[Lang]], w'))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Rendered' m w
m (RWST
(Maybe (Env, FileEnv), FlexForm, [Lang])
Enctype
Ints
Handler
([[Lang]], w))
form
addContent
:: (ToWidget FlexForm (render -> a), Functor m)
=> (render -> a)
-> Rendered' m Widget
-> Rendered' m Widget
addContent :: forall render a (m :: * -> *).
(ToWidget FlexForm (render -> a), Functor m) =>
(render -> a) -> Rendered' m Widget -> Rendered' m Widget
addContent render -> a
content = (Widget -> Widget) -> Rendered' m Widget -> Rendered' m Widget
forall (m :: * -> *) w w'.
Functor m =>
(w -> w') -> Rendered' m w -> Rendered' m w'
applyToWidget (Widget -> Widget -> Widget
forall a b.
WidgetFor FlexForm a
-> WidgetFor FlexForm b -> WidgetFor FlexForm a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* (render -> a) -> Widget
forall site a (m :: * -> *).
(ToWidget site a, MonadWidget m, HandlerSite m ~ site) =>
a -> m ()
forall (m :: * -> *).
(MonadWidget m, HandlerSite m ~ FlexForm) =>
(render -> a) -> m ()
toWidget render -> a
content)
addCss
:: (render ~ RY FlexForm, Functor m)
=> (render -> Css)
-> Rendered' m Widget
-> Rendered' m Widget
addCss :: forall render (m :: * -> *).
(render ~ RY FlexForm, Functor m) =>
(render -> Css) -> Rendered' m Widget -> Rendered' m Widget
addCss = (render -> Css) -> Rendered' m Widget -> Rendered' m Widget
forall render a (m :: * -> *).
(ToWidget FlexForm (render -> a), Functor m) =>
(render -> a) -> Rendered' m Widget -> Rendered' m Widget
addContent
addJs
:: (render ~ RY FlexForm, Functor m)
=> (render -> Javascript)
-> Rendered' m Widget
-> Rendered' m Widget
addJs :: forall render (m :: * -> *).
(render ~ RY FlexForm, Functor m) =>
(render -> Javascript) -> Rendered' m Widget -> Rendered' m Widget
addJs = (render -> Javascript) -> Rendered' m Widget -> Rendered' m Widget
forall render a (m :: * -> *).
(ToWidget FlexForm (render -> a), Functor m) =>
(render -> a) -> Rendered' m Widget -> Rendered' m Widget
addContent
addCssAndJs
:: (render ~ RY FlexForm, Functor m)
=> (render -> Css)
-> (render -> Javascript)
-> Rendered' m Widget
-> Rendered' m Widget
addCssAndJs :: forall render (m :: * -> *).
(render ~ RY FlexForm, Functor m) =>
(render -> Css)
-> (render -> Javascript)
-> Rendered' m Widget
-> Rendered' m Widget
addCssAndJs render -> Css
css render -> Javascript
js = (Widget -> Widget) -> Rendered' m Widget -> Rendered' m Widget
forall (m :: * -> *) w w'.
Functor m =>
(w -> w') -> Rendered' m w -> Rendered' m w'
applyToWidget ((Widget -> Widget -> Widget
forall a b.
WidgetFor FlexForm a
-> WidgetFor FlexForm b -> WidgetFor FlexForm a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* (render -> Css) -> Widget
forall site a (m :: * -> *).
(ToWidget site a, MonadWidget m, HandlerSite m ~ site) =>
a -> m ()
forall (m :: * -> *).
(MonadWidget m, HandlerSite m ~ FlexForm) =>
(render -> Css) -> m ()
toWidget render -> Css
css) (Widget -> Widget) -> (Widget -> Widget) -> Widget -> Widget
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Widget -> Widget -> Widget
forall a b.
WidgetFor FlexForm a
-> WidgetFor FlexForm b -> WidgetFor FlexForm a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* (render -> Javascript) -> Widget
forall site a (m :: * -> *).
(ToWidget site a, MonadWidget m, HandlerSite m ~ site) =>
a -> m ()
forall (m :: * -> *).
(MonadWidget m, HandlerSite m ~ FlexForm) =>
(render -> Javascript) -> m ()
toWidget render -> Javascript
js))
addNameAndCssClass :: Text -> Text -> FieldSettings app
addNameAndCssClass :: forall app. Lang -> Lang -> FieldSettings app
addNameAndCssClass Lang
name Lang
cssClass = FieldSettings app
forall {master}. FieldSettings master
addFieldAttrs
where
fSettings :: FieldSettings site
fSettings = Lang -> FieldSettings site
forall site msg.
RenderMessage site msg =>
msg -> FieldSettings site
fieldSettingsLabel Lang
name
addFieldAttrs :: FieldSettings master
addFieldAttrs = FieldSettings master
forall {master}. FieldSettings master
fSettings {
fsName = Just name,
fsAttrs = addClass cssClass $ fsAttrs fSettings
}
addAttribute :: (Text,Text) -> FieldSettings app -> FieldSettings app
addAttribute :: forall app. (Lang, Lang) -> FieldSettings app -> FieldSettings app
addAttribute (Lang, Lang)
attribute FieldSettings app
fs = FieldSettings app
fs { fsAttrs = attribute : fsAttrs fs}
addAttributes :: [(Text,Text)] -> FieldSettings app -> FieldSettings app
addAttributes :: forall app.
[(Lang, Lang)] -> FieldSettings app -> FieldSettings app
addAttributes [(Lang, Lang)]
as FieldSettings app
fs = FieldSettings app
fs { fsAttrs = as ++ fsAttrs fs}
addCssClass :: Text -> FieldSettings app -> FieldSettings app
addCssClass :: forall app. Lang -> FieldSettings app -> FieldSettings app
addCssClass Lang
c FieldSettings app
fs = FieldSettings app
fs { fsAttrs = addClass c $ fsAttrs fs}
readOnly :: FieldSettings app -> FieldSettings app
readOnly :: forall app. FieldSettings app -> FieldSettings app
readOnly = [(Lang, Lang)] -> FieldSettings app -> FieldSettings app
forall app.
[(Lang, Lang)] -> FieldSettings app -> FieldSettings app
addAttributes [(Lang
"readonly",Lang
""),(Lang
"style",Lang
"background-color: #EEEEEE")]
universalLabel :: String -> SomeMessage FlexForm
universalLabel :: [Char] -> SomeMessage FlexForm
universalLabel = [Char] -> SomeMessage FlexForm
forall a. IsString a => [Char] -> a
fromString
showToUniversalLabel :: Show a => a -> SomeMessage FlexForm
showToUniversalLabel :: forall a. Show a => a -> SomeMessage FlexForm
showToUniversalLabel = [Char] -> SomeMessage FlexForm
universalLabel ([Char] -> SomeMessage FlexForm)
-> (a -> [Char]) -> a -> SomeMessage FlexForm
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> [Char]
forall a. Show a => a -> [Char]
show
newFlexId :: MForm Handler Text
newFlexId :: MForm Handler Lang
newFlexId = HasCallStack => Lang -> Lang -> Lang -> Lang
Lang -> Lang -> Lang -> Lang
T.replace Lang
"h" Lang
"flex" (Lang -> Lang)
-> RWST
(Maybe (Env, FileEnv), FlexForm, [Lang]) Enctype Ints Handler Lang
-> RWST
(Maybe (Env, FileEnv), FlexForm, [Lang]) Enctype Ints Handler Lang
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> RWST
(Maybe (Env, FileEnv), FlexForm, [Lang]) Enctype Ints Handler Lang
forall (m :: * -> *). MonadHandler m => m Lang
newIdent
repeatFlexName :: MForm Handler Text
repeatFlexName :: MForm Handler Lang
repeatFlexName = do
Ints
i <- RWST
(Maybe (Env, FileEnv), FlexForm, [Lang]) Enctype Ints Handler Ints
forall w (m :: * -> *) r s. (Monoid w, Monad m) => RWST r w s m s
RWS.get
Lang
-> RWST
(Maybe (Env, FileEnv), FlexForm, [Lang]) Enctype Ints Handler Lang
forall a.
a
-> RWST
(Maybe (Env, FileEnv), FlexForm, [Lang]) Enctype Ints Handler a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Lang
-> RWST
(Maybe (Env, FileEnv), FlexForm, [Lang]) Enctype Ints Handler Lang)
-> Lang
-> RWST
(Maybe (Env, FileEnv), FlexForm, [Lang]) Enctype Ints Handler Lang
forall a b. (a -> b) -> a -> b
$ [Char] -> Lang
pack ([Char] -> Lang) -> [Char] -> Lang
forall a b. (a -> b) -> a -> b
$ [Char]
"flex" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Ints -> [Char]
forall a. Show a => a -> [Char]
show Ints
i
newFlexName :: MForm Handler Text
newFlexName :: MForm Handler Lang
newFlexName = HasCallStack => Lang -> Lang -> Lang -> Lang
Lang -> Lang -> Lang -> Lang
T.replace Lang
"f" Lang
"flex" (Lang -> Lang)
-> RWST
(Maybe (Env, FileEnv), FlexForm, [Lang]) Enctype Ints Handler Lang
-> RWST
(Maybe (Env, FileEnv), FlexForm, [Lang]) Enctype Ints Handler Lang
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> MForm Handler Lang
RWST
(Maybe (Env, FileEnv), FlexForm, [Lang]) Enctype Ints Handler Lang
forall (m :: * -> *). Monad m => MForm m Lang
newFormIdent
printWidget :: Lang -> Rendered Widget -> IO ()
printWidget :: Lang -> Rendered Widget -> IO ()
printWidget Lang
lang Rendered Widget
render = do
([[Lang]]
_, HtmlDict
dict) <- Rendered Widget -> IO ([[Lang]], HtmlDict)
getFormData Rendered Widget
render
[Char] -> IO ()
putStrLn ([Char] -> IO ()) -> [Char] -> IO ()
forall a b. (a -> b) -> a -> b
$ [Char] -> ([Char] -> [Char]) -> Maybe [Char] -> [Char]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [Char]
"Form not available in this language."
([Char] -> [Char]
trimEnd ([Char] -> [Char]) -> ([Char] -> [Char]) -> [Char] -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [[Char]] -> [Char]
unlines ([[Char]] -> [Char]) -> ([Char] -> [[Char]]) -> [Char] -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> [[Char]] -> [[Char]]
addIndent Int
0 ([[Char]] -> [[Char]])
-> ([Char] -> [[Char]]) -> [Char] -> [[Char]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> [[Char]]
intoLines)
(Maybe [Char] -> [Char]) -> Maybe [Char] -> [Char]
forall a b. (a -> b) -> a -> b
$ Lang -> HtmlDict -> Maybe [Char]
forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup Lang
lang HtmlDict
dict
where
intoLines :: [Char] -> [[Char]]
intoLines [Char]
s =
let opening :: [[Char]]
opening = ([Char] -> [Char]) -> [[Char]] -> [[Char]]
forall a b. (a -> b) -> [a] -> [b]
map ([Char]
"<" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++) ([[Char]] -> [[Char]]) -> [[Char]] -> [[Char]]
forall a b. (a -> b) -> a -> b
$ Int -> [[Char]] -> [[Char]]
forall a. Int -> [a] -> [a]
drop Int
1 ([Char] -> [Char] -> [[Char]]
forall a. (HasCallStack, Eq a) => [a] -> [a] -> [[a]]
splitOn [Char]
"<" [Char]
s)
closing :: [[Char]]
closing = ([Char] -> [[Char]]) -> [[Char]] -> [[Char]]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (([Char] -> Bool) -> [[Char]] -> [[Char]]
forall a. (a -> Bool) -> [a] -> [a]
filter ([Char] -> [Char] -> Bool
forall a. Eq a => a -> a -> Bool
/=[Char]
"") ([[Char]] -> [[Char]])
-> ([Char] -> [[Char]]) -> [Char] -> [[Char]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> [Char] -> [[Char]]
forall a. (HasCallStack, Eq a) => [a] -> [a] -> [[a]]
splitOn [Char]
">") [[Char]]
opening
in ([Char] -> [Char]) -> [[Char]] -> [[Char]]
forall a b. (a -> b) -> [a] -> [b]
map (\[Char]
x -> if [Char]
"<" [Char] -> [Char] -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isPrefixOf` [Char]
x then [Char]
x [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
">" else [Char]
x) [[Char]]
closing
addIndent :: Int -> [[Char]] -> [[Char]]
addIndent Int
_ [] = []
addIndent Int
i ([Char]
s:[[Char]]
ss)
| [Char]
"</" [Char] -> [Char] -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isInfixOf` [Char]
s
= (Int -> Char -> [Char]
forall a. Int -> a -> [a]
replicate (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
2) Char
' ' [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
s) [Char] -> [[Char]] -> [[Char]]
forall a. a -> [a] -> [a]
: Int -> [[Char]] -> [[Char]]
addIndent (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
2) [[Char]]
ss
| [Char]
">" [Char] -> [Char] -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isInfixOf` [Char]
s Bool -> Bool -> Bool
&& Bool -> Bool
not (([Char] -> Bool) -> [[Char]] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any ([Char] -> [Char] -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isInfixOf` [Char]
s) [[Char]]
noClose)
= (Int -> Char -> [Char]
forall a. Int -> a -> [a]
replicate Int
i Char
' ' [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
s) [Char] -> [[Char]] -> [[Char]]
forall a. a -> [a] -> [a]
: Int -> [[Char]] -> [[Char]]
addIndent (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
2) [[Char]]
ss
| Bool
otherwise
= (Int -> Char -> [Char]
forall a. Int -> a -> [a]
replicate Int
i Char
' ' [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
s) [Char] -> [[Char]] -> [[Char]]
forall a. a -> [a] -> [a]
: Int -> [[Char]] -> [[Char]]
addIndent Int
i [[Char]]
ss
noClose :: [[Char]]
noClose =
[ [Char]
"area"
, [Char]
"base"
, [Char]
"br"
, [Char]
"col"
, [Char]
"embed"
, [Char]
"hr"
, [Char]
"img"
, [Char]
"input"
, [Char]
"link"
, [Char]
"meta"
, [Char]
"param"
, [Char]
"source"
, [Char]
"track"
, [Char]
"wbr"
]