@@ -0,0 +1,203 @@
1+{-# LANGUAGE DataKinds #-}
2+{-# LANGUAGE TypeFamilies #-}
3+{-# LANGUAGE TypeOperators #-}
4+{-# LANGUAGE TemplateHaskell #-}
5+{-# LANGUAGE FlexibleInstances #-}
6+{-# LANGUAGE ScopedTypeVariables #-}
7+module Servant.JQuery.Internal where
16+data Segment = Static String -- ^ a static path segment. like "/foo"
17+ | Cap Arg -- ^ a capture. like "/:userid"
21+isCapture :: Segment -> Bool
22+isCapture (Cap _) = True
25+captureArg :: Segment -> Arg
26+captureArg (Cap s) = s
27+captureArg _ = error "captureArg called on non capture"
29+jsSegments :: [Segment] -> String
31+jsSegments [x] = "/" ++ segmentToStr x False
32+jsSegments (x:xs) = "/" ++ segmentToStr x True ++ jsSegments xs
34+segmentToStr :: Segment -> Bool -> String
35+segmentToStr (Static s) notTheEnd =
36+ if notTheEnd then s else s ++ "'"
37+segmentToStr (Cap s) notTheEnd =
38+ "' + " ++ s ++ if notTheEnd then " + '" else ""
48+data QueryArg = QueryArg
50+ , _argType :: ArgType
51+ } deriving (Eq, Show)
55+ , _queryStr :: [QueryArg]
56+ } deriving (Eq, Show)
61+type FunctionName = String
64+data AjaxReq = AjaxReq
66+ , _reqMethod :: Method
68+ , _funcName :: FunctionName
69+ } deriving (Eq, Show)
75+jsParams :: [QueryArg] -> String
77+jsParams [x] = paramToStr x False
78+jsParams (x:xs) = paramToStr x True ++ "&" ++ jsParams xs
80+paramToStr :: QueryArg -> Bool -> String
81+paramToStr qarg notTheEnd =
82+ case qarg ^. argType of
84+ ++ "=' + encodeURIComponent("
86+ ++ if notTheEnd then ") + '" else ")"
91+ ++ "[]=' + encodeURIComponent("
93+ ++ if notTheEnd then ") + '" else ")"
95+ where name = qarg ^. argName
98+defReq = AjaxReq defUrl "GET" False ""
100+class HasJQ layout where
102+ jqueryFor :: Proxy layout -> AjaxReq -> JQ layout
104+instance (HasJQ a, HasJQ b)
105+ => HasJQ (a :<|> b) where
106+ type JQ (a :<|> b) = JQ a :<|> JQ b
108+ jqueryFor Proxy req =
109+ jqueryFor (Proxy :: Proxy a) req
110+ :<|> jqueryFor (Proxy :: Proxy b) req
112+instance (KnownSymbol sym, HasJQ sublayout)
113+ => HasJQ (Capture sym a :> sublayout) where
114+ type JQ (Capture sym a :> sublayout) = JQ sublayout
116+ jqueryFor Proxy req =
117+ jqueryFor (Proxy :: Proxy sublayout) $
118+ req & reqUrl.path <>~ [Cap str]
120+ where str = symbolVal (Proxy :: Proxy sym)
122+instance HasJQ Delete where
123+ type JQ Delete = FunctionName -> AjaxReq
125+ jqueryFor Proxy req fName =
126+ req & funcName .~ fName
127+ & reqMethod .~ "DELETE"
129+instance HasJQ (Get a) where
130+ type JQ (Get a) = FunctionName -> AjaxReq
132+ jqueryFor Proxy req fName =
133+ req & funcName .~ fName
134+ & reqMethod .~ "GET"
136+instance HasJQ (Post a) where
137+ type JQ (Post a) = FunctionName -> AjaxReq
139+ jqueryFor Proxy req fName =
140+ req & funcName .~ fName
141+ & reqMethod .~ "POST"
143+instance HasJQ (Put a) where
144+ type JQ (Put a) = FunctionName -> AjaxReq
146+ jqueryFor Proxy req fName =
147+ req & funcName .~ fName
148+ & reqMethod .~ "PUT"
150+instance (KnownSymbol sym, HasJQ sublayout)
151+ => HasJQ (QueryParam sym a :> sublayout) where
152+ type JQ (QueryParam sym a :> sublayout) = JQ sublayout
154+ jqueryFor Proxy req =
155+ jqueryFor (Proxy :: Proxy sublayout) $
156+ req & reqUrl.queryStr <>~ [QueryArg str Normal]
158+ where str = symbolVal (Proxy :: Proxy sym)
159+ strArg = str ++ "Value"
161+instance (KnownSymbol sym, HasJQ sublayout)
162+ => HasJQ (QueryParams sym a :> sublayout) where
163+ type JQ (QueryParams sym a :> sublayout) = JQ sublayout
165+ jqueryFor Proxy req =
166+ jqueryFor (Proxy :: Proxy sublayout) $
167+ req & reqUrl.queryStr <>~ [QueryArg str List]
169+ where str = symbolVal (Proxy :: Proxy sym)
171+instance (KnownSymbol sym, HasJQ sublayout)
172+ => HasJQ (QueryFlag sym :> sublayout) where
173+ type JQ (QueryFlag sym :> sublayout) = JQ sublayout
175+ jqueryFor Proxy req =
176+ jqueryFor (Proxy :: Proxy sublayout) $
177+ req & reqUrl.queryStr <>~ [QueryArg str Flag]
179+ where str = symbolVal (Proxy :: Proxy sym)
181+instance HasJQ Raw where
182+ type JQ Raw = Method -> FunctionName -> AjaxReq
184+ jqueryFor Proxy req method fName =
185+ req & reqMethod .~ method
188+instance HasJQ sublayout => HasJQ (ReqBody a :> sublayout) where
189+ type JQ (ReqBody a :> sublayout) = JQ sublayout
191+ jqueryFor Proxy req =
192+ jqueryFor (Proxy :: Proxy sublayout) $
193+ req & reqBody .~ True
195+instance (KnownSymbol path, HasJQ sublayout)
196+ => HasJQ (path :> sublayout) where
197+ type JQ (path :> sublayout) = JQ sublayout
199+ jqueryFor Proxy req =
200+ jqueryFor (Proxy :: Proxy sublayout) $
201+ req & reqUrl.path <>~ [Static str]
203+ where str = symbolVal (Proxy :: Proxy path)