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) | ||
