module Controller.Angular
( JSOpt(..)
, jsURL
, angular
, angularRequest
) where
import Control.Arrow (second)
import qualified Data.ByteString as BS
import qualified Data.ByteString.Builder as BSB
import Data.Default.Class (Default(..))
import Network.HTTP.Types (hUserAgent, QueryLike(..))
import qualified Network.Wai as Wai
import qualified Text.Regex.Posix as Regex
import Has
import Action
import HTTP (encodePath')
import HTTP.Request
import View.Angular
import Web
import Web.Service (Web, getWebVersion)
data JSOpt
= JSDisabled
| JSDefault
| JSEnabled
deriving (Eq, Ord)
instance Default JSOpt where
def = JSDefault
instance Monoid JSOpt where
mempty = JSDefault
mappend JSDefault j = j
mappend j _ = j
instance QueryLike JSOpt where
toQuery JSDisabled = [("js", Just "0")]
toQuery JSDefault = []
toQuery JSEnabled = [("js", Just "1")]
jsEnable :: Bool -> JSOpt
jsEnable False = JSDisabled
jsEnable True = JSEnabled
jsURL
:: JSOpt
-> Wai.Request
-> (JSOpt, BSB.Builder)
jsURL js req =
second (encodePath' (Wai.pathInfo req) . (toQuery js ++))
$ unjs
$ Wai.queryString req
where
unjs [] = (JSDefault, [])
unjs (("js", v) : q) = (jsEnable (boolParameterValue v), snd $ unjs q)
unjs (x : q) = second (x :) $ unjs q
browserBlacklist :: Regex.Regex
browserBlacklist = Regex.makeRegex
("^Mozilla/.* \\(.*\\<(MSIE [0-9]\\.[0-9]|AppleWebKit/.* Version/[0-5]\\..* Safari/)" :: String)
enableAngular :: JSOpt -> Wai.Request -> Bool
enableAngular JSDisabled = const False
enableAngular JSDefault = not . any (Regex.matchTest browserBlacklist) . lookupRequestHeader hUserAgent
enableAngular JSEnabled = const True
angularRequest :: Wai.Request -> Maybe BSB.Builder
angularRequest req =
if enableAngular jsopt req
then Just nojs
else Nothing
where (jsopt, nojs) = jsURL JSDisabled req
angularResult :: BS.ByteString -> BSB.Builder -> RequestContext -> IO ()
angularResult version nojs reqCtx = do
cssDeps <- (:[]) <$> makeWebFilePath "all.min.css"
jsDeps <- (:[]) <$> makeWebFilePath "all.min.js"
result $ okResponse [] (htmlAngular version cssDeps jsDeps nojs reqCtx)
angular :: Handler ()
angular = do
(servWeb :: Web) <- peek
let version = getWebVersion servWeb
(b :: Maybe BSB.Builder) <- peeks angularRequest
mapM_ (focusIO . angularResult version) b