diff options
| -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 |
