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 | |
parent | 37f0dac79707a0de81ec6364d2704007eefd9289 (diff) | |
download | bar-3cd4169e33c07b71129aafcecfb81a3b5007fa39.tar bar-3cd4169e33c07b71129aafcecfb81a3b5007fa39.tar.gz bar-3cd4169e33c07b71129aafcecfb81a3b5007fa39.tar.bz2 bar-3cd4169e33c07b71129aafcecfb81a3b5007fa39.tar.xz bar-3cd4169e33c07b71129aafcecfb81a3b5007fa39.zip |
Autocomplete types
-rw-r--r-- | Application.hs | 1 | ||||
-rw-r--r-- | Handler/Common.hs | 126 | ||||
-rw-r--r-- | Handler/Types.hs | 15 | ||||
-rw-r--r-- | Settings.hs | 2 | ||||
-rw-r--r-- | bar.cabal | 1 | ||||
-rw-r--r-- | config/routes | 3 |
6 files changed, 97 insertions, 51 deletions
diff --git a/Application.hs b/Application.hs index 85ceb2f..3a16e88 100644 --- a/Application.hs +++ b/Application.hs | |||
@@ -41,6 +41,7 @@ import Handler.ReferenceListing | |||
41 | import Handler.ReferenceItem | 41 | import Handler.ReferenceItem |
42 | import Handler.DeleteRefItem | 42 | import Handler.DeleteRefItem |
43 | import Handler.Kinds | 43 | import Handler.Kinds |
44 | import Handler.Types | ||
44 | import Handler.List | 45 | import Handler.List |
45 | 46 | ||
46 | -- This line actually creates our YesodDispatch instance. It is the second half | 47 | -- This line actually creates our YesodDispatch instance. It is the second half |
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) | ||
diff --git a/Settings.hs b/Settings.hs index d0e16ea..a15fb03 100644 --- a/Settings.hs +++ b/Settings.hs | |||
@@ -19,7 +19,7 @@ import Yesod.Default.Config2 (applyEnvValue, configSettingsYml) | |||
19 | import Yesod.Default.Util (WidgetFileSettings, widgetFileNoReload, | 19 | import Yesod.Default.Util (WidgetFileSettings, widgetFileNoReload, |
20 | widgetFileReload) | 20 | widgetFileReload) |
21 | 21 | ||
22 | import Thermoprint.Client (BaseUrl(..), Scheme(..), InvalidBaseUrlException, parseBaseUrl) | 22 | import Thermoprint.Client (BaseUrl(..), parseBaseUrl) |
23 | 23 | ||
24 | #ifdef DEVELOPMENT | 24 | #ifdef DEVELOPMENT |
25 | #define DEV_BOOL True | 25 | #define DEV_BOOL True |
@@ -31,6 +31,7 @@ library | |||
31 | Handler.ReferenceItem | 31 | Handler.ReferenceItem |
32 | Handler.DeleteRefItem | 32 | Handler.DeleteRefItem |
33 | Handler.Kinds | 33 | Handler.Kinds |
34 | Handler.Types | ||
34 | Handler.List | 35 | Handler.List |
35 | 36 | ||
36 | if flag(dev) || flag(library-only) | 37 | if flag(dev) || flag(library-only) |
diff --git a/config/routes b/config/routes index 6ed3204..5024ab1 100644 --- a/config/routes +++ b/config/routes | |||
@@ -11,4 +11,7 @@ | |||
11 | /ref/#ReferenceId/delete DeleteRefItemR POST | 11 | /ref/#ReferenceId/delete DeleteRefItemR POST |
12 | 12 | ||
13 | /kinds KindsR GET | 13 | /kinds KindsR GET |
14 | /types TypesR GET | ||
15 | /type TypeR GET | ||
16 | |||
14 | /list ListR GET POST | 17 | /list ListR GET POST |