diff options
author | Gregor Kleen <gkleen@yggdrasil.li> | 2017-03-15 18:11:47 +0100 |
---|---|---|
committer | Gregor Kleen <gkleen@yggdrasil.li> | 2017-03-15 18:11:47 +0100 |
commit | 3cd4169e33c07b71129aafcecfb81a3b5007fa39 (patch) | |
tree | 261de0303273cc1a861977dc9aebce235d0afe51 /Handler | |
parent | 37f0dac79707a0de81ec6364d2704007eefd9289 (diff) | |
download | bar-3cd4169e33c07b71129aafcecfb81a3b5007fa39.tar bar-3cd4169e33c07b71129aafcecfb81a3b5007fa39.tar.gz bar-3cd4169e33c07b71129aafcecfb81a3b5007fa39.tar.bz2 bar-3cd4169e33c07b71129aafcecfb81a3b5007fa39.tar.xz bar-3cd4169e33c07b71129aafcecfb81a3b5007fa39.zip |
Autocomplete types
Diffstat (limited to 'Handler')
-rw-r--r-- | Handler/Common.hs | 126 | ||||
-rw-r--r-- | Handler/Types.hs | 15 |
2 files changed, 91 insertions, 50 deletions
diff --git a/Handler/Common.hs b/Handler/Common.hs index 65988da..a1ae34b 100644 --- a/Handler/Common.hs +++ b/Handler/Common.hs | |||
@@ -26,6 +26,8 @@ import Control.Lens | |||
26 | 26 | ||
27 | import Handler.Common.Types | 27 | import Handler.Common.Types |
28 | 28 | ||
29 | import Text.Julius (RawJS(..)) | ||
30 | |||
29 | dayFormat :: Day -> String | 31 | dayFormat :: Day -> String |
30 | dayFormat = formatTime defaultTimeLocale "%e. %b %y" | 32 | dayFormat = formatTime defaultTimeLocale "%e. %b %y" |
31 | 33 | ||
@@ -36,8 +38,12 @@ itemForm proto identView = do | |||
36 | 38 | ||
37 | t <- lift . runDB $ maybe (return Nothing) (fmap (Just . kindType) . getType) proto | 39 | t <- lift . runDB $ maybe (return Nothing) (fmap (Just . kindType) . getType) proto |
38 | 40 | ||
39 | (kindRes, kindWidget) <- kindField $ itemKind <$> proto | 41 | let kt kWidget tWidget = |
40 | (typeRes, typeWidget) <- typeField $ t | 42 | [whamlet| |
43 | <div .td>^{kWidget} | ||
44 | <div .td>^{tWidget} | ||
45 | |] | ||
46 | ((kindRes, typeRes), typedKindWidget) <- typedKindField kt ((itemKind <$> proto), t) | ||
41 | (boughtRes, boughtWidget) <- dayForm (maybe (Just $ Just today) Just $ fmap itemBought proto) "Unknown" | 47 | (boughtRes, boughtWidget) <- dayForm (maybe (Just $ Just today) Just $ fmap itemBought proto) "Unknown" |
42 | (expiresRes, expiresWidget) <- dayForm (fmap itemExpires proto) "Never" | 48 | (expiresRes, expiresWidget) <- dayForm (fmap itemExpires proto) "Never" |
43 | (openedRes, openedWidget) <- dayForm (fmap itemOpened proto) "Never" | 49 | (openedRes, openedWidget) <- dayForm (fmap itemOpened proto) "Never" |
@@ -54,8 +60,7 @@ itemForm proto identView = do | |||
54 | [whamlet| | 60 | [whamlet| |
55 | $newline never | 61 | $newline never |
56 | #{identView} | 62 | #{identView} |
57 | <div .td>^{kindWidget} | 63 | ^{typedKindWidget} |
58 | <div .td>^{typeWidget} | ||
59 | <div .td>^{boughtWidget} | 64 | <div .td>^{boughtWidget} |
60 | <div .td>^{expiresWidget} | 65 | <div .td>^{expiresWidget} |
61 | <div .td>^{openedWidget} | 66 | <div .td>^{openedWidget} |
@@ -93,9 +98,14 @@ referenceForm :: Maybe Reference -- ^ Update existing item or insert new? | |||
93 | -> Html -> MForm Handler (FormResult (WithType Reference), Widget) | 98 | -> Html -> MForm Handler (FormResult (WithType Reference), Widget) |
94 | referenceForm proto identView = do | 99 | referenceForm proto identView = do |
95 | t <- lift . runDB $ maybe (return Nothing) (fmap (Just . kindType) . getType) proto | 100 | t <- lift . runDB $ maybe (return Nothing) (fmap (Just . kindType) . getType) proto |
101 | |||
102 | let kt kWidget tWidget = | ||
103 | [whamlet| | ||
104 | <div .td>^{kWidget} | ||
105 | <div .td>^{tWidget} | ||
106 | |] | ||
96 | 107 | ||
97 | (kindRes, kindWidget) <- kindField $ referenceKind <$> proto | 108 | ((kindRes, typeRes), typedKindWidget) <- typedKindField kt ((referenceKind <$> proto), t) |
98 | (typeRes, typeWidget) <- typeField $ t | ||
99 | 109 | ||
100 | let referenceRes = do | 110 | let referenceRes = do |
101 | referenceKind <- kindRes | 111 | referenceKind <- kindRes |
@@ -106,63 +116,79 @@ referenceForm proto identView = do | |||
106 | [whamlet| | 116 | [whamlet| |
107 | $newline never | 117 | $newline never |
108 | #{identView} | 118 | #{identView} |
109 | <div .td>^{kindWidget} | 119 | ^{typedKindWidget} |
110 | <div .td>^{typeWidget} | ||
111 | |] | 120 | |] |
112 | 121 | ||
113 | referenceListing :: ReferenceState -> Widget | 122 | referenceListing :: ReferenceState -> Widget |
114 | referenceListing ReferenceState{ refFormState = formState, ..} = $(widgetFile "referenceListing") | 123 | referenceListing ReferenceState{ refFormState = formState, ..} = $(widgetFile "referenceListing") |
115 | 124 | ||
116 | kindField :: Maybe Text -> MForm Handler (FormResult Text, Widget) | 125 | typedKindField :: (Widget -> Widget -> Widget) -- ^ `\kindWidget typeWidget -> _` |
117 | kindField proto = do | 126 | -> (Maybe Text, Maybe Text) -- ^ `(kindProto, typeProto)` |
118 | optionId <- ("options" <>) . tshow . hashUnique <$> liftIO newUnique | 127 | -> MForm Handler ((FormResult Text, FormResult Text), Widget) -- ^ `((kindRes, typeRes), typedKindWidget)` |
119 | 128 | typedKindField collate (kindProto, typeProto) = do | |
129 | tOptionId <- ("options" <>) . tshow . hashUnique <$> liftIO newUnique | ||
120 | let | 130 | let |
121 | attrs = [ ("list", optionId) | 131 | tAttrs = [ ("list", tOptionId) |
122 | , ("autocomplete", "off") | 132 | , ("autocomplete", "off") |
123 | ] | 133 | ] |
124 | 134 | kOptionId <- ("options" <>) . tshow . hashUnique <$> liftIO newUnique | |
125 | (kindRes, kindView) <- mreq textField ("" { fsAttrs = attrs }) proto | ||
126 | |||
127 | options <- lift kinds | ||
128 | |||
129 | return . (kindRes, ) $ | ||
130 | [whamlet| | ||
131 | $newline never | ||
132 | ^{fvInput kindView} | ||
133 | <datalist ##{optionId}> | ||
134 | $forall opt <- options | ||
135 | <option value=#{opt}> | ||
136 | |] | ||
137 | |||
138 | typeField :: Maybe Text -> MForm Handler (FormResult Text, Widget) | ||
139 | typeField proto = do | ||
140 | optionId <- ("options" <>) . tshow . hashUnique <$> liftIO newUnique | ||
141 | 135 | ||
142 | let | 136 | let |
143 | attrs = [ ("list", optionId) | 137 | kAttrs = [ ("list", kOptionId) |
144 | , ("autocomplete", "off") | 138 | , ("autocomplete", "off") |
145 | ] | 139 | ] |
146 | 140 | ||
147 | (typeRes, typeView) <- mreq textField ("" { fsAttrs = attrs }) proto | 141 | (kindRes, kindView) <- mreq textField ("" { fsAttrs = kAttrs }) kindProto |
148 | 142 | (typeRes, typeView) <- mreq textField ("" { fsAttrs = tAttrs }) typeProto | |
149 | (Set.fromList . map (kindType . entityVal) -> options) <- lift . runDB $ selectList [] [] | 143 | |
150 | 144 | kOptions <- lift kinds | |
151 | return . (typeRes, ) $ | 145 | (Set.fromList . map (kindType . entityVal) -> tOptions) <- lift . runDB $ selectList [] [] |
152 | [whamlet| | 146 | |
153 | $newline never | 147 | return . ((kindRes, typeRes), ) $ do |
154 | ^{fvInput typeView} | 148 | toWidget $ |
155 | <datalist ##{optionId}> | 149 | [julius| |
156 | $forall opt <- Set.toList options | 150 | $(function () { |
157 | <option value=#{opt}> | 151 | $("##{rawJS $ fvId kindView}").change(function () { |
158 | |] | 152 | $.ajax({ |
153 | url: '@{TypeR}', | ||
154 | type: 'GET', | ||
155 | contentType: 'application/json', | ||
156 | data: { | ||
157 | kind: $(this).val() | ||
158 | }, | ||
159 | success: function (answer) { | ||
160 | $("##{rawJS $ fvId typeView}").val(answer); | ||
161 | typeChanged = false; | ||
162 | } | ||
163 | }); | ||
164 | }) ; | ||
165 | }); | ||
166 | |] | ||
167 | let | ||
168 | kindWidget = | ||
169 | [whamlet| | ||
170 | $newline never | ||
171 | ^{fvInput kindView} | ||
172 | <datalist ##{kOptionId}> | ||
173 | $forall opt <- kOptions | ||
174 | <option value=#{opt}> | ||
175 | |] | ||
176 | typeWidget = | ||
177 | [whamlet| | ||
178 | $newline never | ||
179 | ^{fvInput typeView} | ||
180 | <datalist ##{tOptionId}> | ||
181 | $forall opt <- tOptions | ||
182 | <option value=#{opt}> | ||
183 | |] | ||
184 | collate kindWidget typeWidget | ||
159 | 185 | ||
160 | kinds :: Handler [Text] | 186 | kinds :: Handler (Set Text) |
161 | kinds = do | 187 | kinds = do |
162 | stock <- runDB $ selectList [] [] | 188 | stock <- runDB $ selectList [] [] |
163 | reference <- runDB $ selectList [] [] | 189 | reference <- runDB $ selectList [] [] |
164 | 190 | ||
165 | return $ concat | 191 | return . Set.fromList $ concat |
166 | [ [ itemKind | Entity _ Item{..} <- stock ] | 192 | [ [ itemKind | Entity _ Item{..} <- stock ] |
167 | , [ referenceKind | Entity _ Reference{..} <- reference ] | 193 | , [ referenceKind | Entity _ Reference{..} <- reference ] |
168 | ] | 194 | ] |
diff --git a/Handler/Types.hs b/Handler/Types.hs new file mode 100644 index 0000000..04055ad --- /dev/null +++ b/Handler/Types.hs | |||
@@ -0,0 +1,15 @@ | |||
1 | module Handler.Types where | ||
2 | |||
3 | import Import | ||
4 | |||
5 | import Data.Set (Set) | ||
6 | import qualified Data.Set as Set | ||
7 | |||
8 | getTypesR :: Handler Value | ||
9 | getTypesR = returnJson <=< runDB $ do | ||
10 | Set.fromList . map (kindType . entityVal) <$> selectList [] [] | ||
11 | |||
12 | getTypeR :: Handler Value | ||
13 | getTypeR = do | ||
14 | kind <- maybe (invalidArgs ["kind"]) return =<< lookupGetParam "kind" | ||
15 | returnJson <=< runDB $ kindType . entityVal <$> getBy404 (UniqueKind $ normalizeKind kind) | ||