summaryrefslogtreecommitdiff
path: root/Handler
diff options
context:
space:
mode:
authorGregor Kleen <gkleen@yggdrasil.li>2017-03-14 18:33:42 +0100
committerGregor Kleen <gkleen@yggdrasil.li>2017-03-14 18:33:42 +0100
commit7bc954b779a9bc4e1c5e60f2648101c62ed22e72 (patch)
treeb30851324772c14550c0444b7e79e36256f67900 /Handler
parent53fcf55c02f9335518c28d26429913258fc28f87 (diff)
downloadbar-7bc954b779a9bc4e1c5e60f2648101c62ed22e72.tar
bar-7bc954b779a9bc4e1c5e60f2648101c62ed22e72.tar.gz
bar-7bc954b779a9bc4e1c5e60f2648101c62ed22e72.tar.bz2
bar-7bc954b779a9bc4e1c5e60f2648101c62ed22e72.tar.xz
bar-7bc954b779a9bc4e1c5e60f2648101c62ed22e72.zip
Reference & list
Diffstat (limited to 'Handler')
-rw-r--r--Handler/Common.hs64
-rw-r--r--Handler/Common/Types.hs23
-rw-r--r--Handler/DeleteRefItem.hs10
-rw-r--r--Handler/InventoryListing.hs2
-rw-r--r--Handler/Item.hs10
-rw-r--r--Handler/Kinds.hs8
-rw-r--r--Handler/List.hs71
-rw-r--r--Handler/ReferenceItem.hs25
-rw-r--r--Handler/ReferenceListing.hs27
-rw-r--r--Handler/UpdateItem.hs20
10 files changed, 235 insertions, 25 deletions
diff --git a/Handler/Common.hs b/Handler/Common.hs
index 38fb1ce..2416d15 100644
--- a/Handler/Common.hs
+++ b/Handler/Common.hs
@@ -3,8 +3,13 @@
3module Handler.Common 3module Handler.Common
4 ( inventoryListing 4 ( inventoryListing
5 , itemForm 5 , itemForm
6 , referenceListing
7 , referenceForm
8 , kinds
6 , InventoryState(..) 9 , InventoryState(..)
10 , ReferenceState(..)
7 , FormState(..) 11 , FormState(..)
12 , HasFormState(..)
8 ) where 13 ) where
9 14
10import Import 15import Import
@@ -25,7 +30,7 @@ itemForm :: Maybe Item -- ^ Update existing item or insert new?
25itemForm proto identView = do 30itemForm proto identView = do
26 today <- utctDay <$> liftIO getCurrentTime 31 today <- utctDay <$> liftIO getCurrentTime
27 32
28 (kindRes, kindView) <- mreq textField "" $ itemKind <$> proto 33 (kindRes, kindWidget) <- kindField $ itemKind <$> proto
29 (boughtRes, boughtWidget) <- dayForm (maybe (Just $ Just today) Just $ fmap itemBought proto) "Unknown" 34 (boughtRes, boughtWidget) <- dayForm (maybe (Just $ Just today) Just $ fmap itemBought proto) "Unknown"
30 (expiresRes, expiresWidget) <- dayForm (fmap itemExpires proto) "Never" 35 (expiresRes, expiresWidget) <- dayForm (fmap itemExpires proto) "Never"
31 (openedRes, openedWidget) <- dayForm (fmap itemOpened proto) "Never" 36 (openedRes, openedWidget) <- dayForm (fmap itemOpened proto) "Never"
@@ -41,7 +46,7 @@ itemForm proto identView = do
41 [whamlet| 46 [whamlet|
42 $newline never 47 $newline never
43 #{identView} 48 #{identView}
44 <div .td>^{fvInput kindView} 49 <div .td>^{kindWidget}
45 <div .td>^{boughtWidget} 50 <div .td>^{boughtWidget}
46 <div .td>^{expiresWidget} 51 <div .td>^{expiresWidget}
47 <div .td>^{openedWidget} 52 <div .td>^{openedWidget}
@@ -73,6 +78,55 @@ itemForm proto identView = do
73 |] 78 |]
74 79
75inventoryListing :: InventoryState -> Widget 80inventoryListing :: InventoryState -> Widget
76inventoryListing InventoryState{..} = do 81inventoryListing InventoryState{ invFormState = formState, ..} = $(widgetFile "inventoryListing")
77 setTitle "Bar Inventory" 82
78 $(widgetFile "inventoryListing") 83referenceForm :: Maybe Reference -- ^ Update existing item or insert new?
84 -> Html -> MForm Handler (FormResult Reference, Widget)
85referenceForm proto identView = do
86 (kindRes, kindWidget) <- kindField $ referenceKind <$> proto
87
88 let referenceRes = do
89 referenceKind <- kindRes
90 return Reference{ referenceNormKind = normalizeKind referenceKind, .. }
91
92 return . (referenceRes, ) $
93 [whamlet|
94 $newline never
95 #{identView}
96 <div .td>^{kindWidget}
97 |]
98
99referenceListing :: ReferenceState -> Widget
100referenceListing ReferenceState{ refFormState = formState, ..} = $(widgetFile "referenceListing")
101
102kindField :: Maybe Text -> MForm Handler (FormResult Text, Widget)
103kindField proto = do
104 optionId <- ("options" <>) . tshow . hashUnique <$> liftIO newUnique
105
106 let
107 attrs = [ ("list", optionId)
108 , ("autocomplete", "off")
109 ]
110
111 (kindRes, kindView) <- mreq textField ("" { fsAttrs = attrs }) proto
112
113 options <- lift kinds
114
115 return . (kindRes, ) $
116 [whamlet|
117 $newline never
118 ^{fvInput kindView}
119 <datalist ##{optionId}>
120 $forall opt <- options
121 <option value=#{opt}>
122 |]
123
124kinds :: Handler [Text]
125kinds = do
126 stock <- runDB $ selectList [] []
127 reference <- runDB $ selectList [] []
128
129 return $ concat
130 [ [ itemKind | Entity _ Item{..} <- stock ]
131 , [ referenceKind | Entity _ Reference{..} <- reference ]
132 ]
diff --git a/Handler/Common/Types.hs b/Handler/Common/Types.hs
index ca7cb8d..08653af 100644
--- a/Handler/Common/Types.hs
+++ b/Handler/Common/Types.hs
@@ -8,15 +8,32 @@ import Control.Lens
8 8
9data InventoryState = InventoryState 9data InventoryState = InventoryState
10 { stock :: [Entity Item] 10 { stock :: [Entity Item]
11 , formState :: Maybe FormState 11 , invFormState :: Maybe (FormState ItemId)
12 } 12 }
13 13
14data FormState = InsertForm 14data ReferenceState = ReferenceState
15 { reference :: [Entity Reference]
16 , refFormState :: Maybe (FormState ReferenceId)
17 }
18
19class HasFormState a where
20 type family UpdateId a :: *
21 formState :: a -> Maybe (FormState (UpdateId a))
22
23instance HasFormState InventoryState where
24 type UpdateId InventoryState = ItemId
25 formState = invFormState
26
27instance HasFormState ReferenceState where
28 type UpdateId ReferenceState = ReferenceId
29 formState = refFormState
30
31data FormState id = InsertForm
15 { fsInsertForm :: Widget 32 { fsInsertForm :: Widget
16 , fsInsertEncoding :: Enctype 33 , fsInsertEncoding :: Enctype
17 } 34 }
18 | UpdateForm 35 | UpdateForm
19 { fsUpdateItem :: ItemId 36 { fsUpdateId :: id
20 , fsUpdateForm :: Widget 37 , fsUpdateForm :: Widget
21 , fsUpdateEncoding :: Enctype 38 , fsUpdateEncoding :: Enctype
22 } 39 }
diff --git a/Handler/DeleteRefItem.hs b/Handler/DeleteRefItem.hs
new file mode 100644
index 0000000..c4ff519
--- /dev/null
+++ b/Handler/DeleteRefItem.hs
@@ -0,0 +1,10 @@
1module Handler.DeleteRefItem where
2
3import Import
4
5postDeleteRefItemR :: ReferenceId -> Handler TypedContent
6postDeleteRefItemR referenceId = do
7 runDB $ delete referenceId
8 selectRep $ do
9 provideJson ()
10 provideRep (redirect $ ReferenceListingR :: Handler Html)
diff --git a/Handler/InventoryListing.hs b/Handler/InventoryListing.hs
index e3c062e..12f36ba 100644
--- a/Handler/InventoryListing.hs
+++ b/Handler/InventoryListing.hs
@@ -18,7 +18,7 @@ postInventoryListingR = do
18 selectRep $ do 18 selectRep $ do
19 provideJson (stock :: [Entity Item]) 19 provideJson (stock :: [Entity Item])
20 provideRep . defaultLayout $ inventoryListing InventoryState 20 provideRep . defaultLayout $ inventoryListing InventoryState
21 { formState = Just InsertForm{..} 21 { invFormState = Just InsertForm{..}
22 , .. 22 , ..
23 } 23 }
24 24
diff --git a/Handler/Item.hs b/Handler/Item.hs
index 87030bb..0f48261 100644
--- a/Handler/Item.hs
+++ b/Handler/Item.hs
@@ -4,12 +4,10 @@ import Import
4 4
5getItemR :: ItemId -> Handler TypedContent 5getItemR :: ItemId -> Handler TypedContent
6getItemR itemId = do 6getItemR itemId = do
7 eLookup <- runDB $ fmap (Entity itemId) <$> get itemId 7 entity <- runDB $ Entity itemId <$> get404 itemId
8 case eLookup of 8 selectRep $ do
9 Nothing -> notFound 9 provideJson entity
10 Just entity -> selectRep $ do 10 provideRep (redirect $ InventoryListingR :#: itemId :: Handler Html)
11 provideJson entity
12 provideRep (redirect $ InventoryListingR :#: itemId :: Handler Html)
13 11
14putItemR :: ItemId -> Handler Value 12putItemR :: ItemId -> Handler Value
15putItemR itemId = do 13putItemR itemId = do
diff --git a/Handler/Kinds.hs b/Handler/Kinds.hs
new file mode 100644
index 0000000..0843c70
--- /dev/null
+++ b/Handler/Kinds.hs
@@ -0,0 +1,8 @@
1module Handler.Kinds where
2
3import Import
4
5import Handler.Common
6
7getKindsR :: Handler Value
8getKindsR = returnJson =<< kinds
diff --git a/Handler/List.hs b/Handler/List.hs
new file mode 100644
index 0000000..cfd3f7c
--- /dev/null
+++ b/Handler/List.hs
@@ -0,0 +1,71 @@
1{-# LANGUAGE ApplicativeDo #-}
2{-# LANGUAGE OverloadedLists #-}
3
4module Handler.List where
5
6import Import
7
8import Data.Set (Set)
9import qualified Data.Set as Set
10
11import Data.Map (Map)
12import qualified Data.Map as Map
13
14import qualified Data.Text as Text
15import qualified Data.Text.Lazy as Lazy.Text
16
17import Database.Persist.Sql (Single(..), rawSql)
18
19import Thermoprint.Client
20
21list :: Handler (Set Text)
22list = do
23 (map unSingle -> kinds) <- runDB $ rawSql "select reference.kind from reference where not exists (select * from item where COALESCE(item.expires >= CURRENT_DATE, TRUE) and (item.norm_kind = reference.norm_kind)) " []
24 return $ Set.fromList kinds
25
26mkPrintout :: Set Text -> Printout
27mkPrintout list = Printout
28 [ Paragraph
29 [Cooked . either id Line . text . Lazy.Text.fromStrict . Text.unlines . map (" - " <>) $ Set.toAscList list
30 ]
31 ]
32
33getListR, postListR :: Handler TypedContent
34getListR = postListR
35postListR = do
36 Client{..} <- mkClient' . appThermoprintBase . appSettings <$> getYesod
37 let
38 formatPrinter (pId@(PrinterId num), pStatus) =
39 ("Printer #" <> tshow num <> " – " <> tshow pStatus, pId)
40 printers' <- map formatPrinter . Map.toAscList <$> printers
41 list <- list
42
43 ((printResult, printView), printEnc) <- runFormPost . renderDivsNoLabels $ do
44 pId <- case printers' of
45 [(_, pId)] -> pure pId
46 _ -> areq (selectFieldList printers') "Printer" . listToMaybe $ map snd printers'
47 pure pId
48
49 case printResult of
50 FormSuccess pId -> do
51 (JobId jId) <- jobCreate (Just pId) $ mkPrintout list
52 addMessage "printSuccess" . toHtml $ "List is printing as job #" <> tshow jId
53 FormFailure errors -> mapM_ (addMessage "formError" . toHtml) errors
54 _ -> return ()
55
56 selectRep $ do
57 provideJson list
58 provideRep . defaultLayout $
59 [whamlet|
60 <div .table .main>
61 <div .tr .sepBelow>
62 <div .th>Item
63 $forall item <- Set.toAscList list
64 <div .tr .color>
65 <div .kind>#{item}
66 <form .tr .sepAbove method=post action=@{ListR} enctype=#{printEnc}>
67 <div .td>
68 ^{printView}
69 <button type=submit :Set.null list:disabled>
70 Print
71 |]
diff --git a/Handler/ReferenceItem.hs b/Handler/ReferenceItem.hs
new file mode 100644
index 0000000..738c9f3
--- /dev/null
+++ b/Handler/ReferenceItem.hs
@@ -0,0 +1,25 @@
1module Handler.ReferenceItem where
2
3import Import
4
5getReferenceItemR :: ReferenceId -> Handler TypedContent
6getReferenceItemR referenceId = do
7 entity <- runDB $ Entity referenceId <$> get404 referenceId
8 selectRep $ do
9 provideJson entity
10 provideRep (redirect $ ReferenceListingR :#: referenceId :: Handler Html)
11
12
13putReferenceItemR :: ReferenceId -> Handler Value
14putReferenceItemR referenceId = do
15 Reference{..} <- requireCheckJsonBody
16 returnJson . Entity referenceId =<< runDB
17 (updateGet referenceId [ ReferenceKind =. referenceKind
18 , ReferenceNormKind =. referenceNormKind
19 ])
20
21patchReferenceItemR :: ReferenceId -> Handler Value
22patchReferenceItemR = putReferenceItemR -- Just one field
23
24deleteReferenceItemR :: ReferenceId -> Handler ()
25deleteReferenceItemR = runDB . delete
diff --git a/Handler/ReferenceListing.hs b/Handler/ReferenceListing.hs
new file mode 100644
index 0000000..0f777ee
--- /dev/null
+++ b/Handler/ReferenceListing.hs
@@ -0,0 +1,27 @@
1module Handler.ReferenceListing where
2
3import Import
4
5import Handler.Common
6
7getReferenceListingR, postReferenceListingR :: Handler TypedContent
8getReferenceListingR = postReferenceListingR
9postReferenceListingR = do
10 ((insertResult, fsInsertForm), fsInsertEncoding) <- runFormPost $ referenceForm Nothing
11
12 mapM_ (addMessage "formError" . toHtml) =<< case insertResult of
13 FormSuccess newReference -> [] <$ runDB (insert newReference)
14 FormFailure errors -> return errors
15 _ -> return []
16
17 reference <- runDB $ selectList [] [Asc ReferenceKind]
18
19 selectRep $ do
20 provideJson (reference :: [Entity Reference])
21 provideRep . defaultLayout $ referenceListing ReferenceState
22 { refFormState = Just InsertForm{..}
23 , ..
24 }
25
26putReferenceListingR :: Handler Value
27putReferenceListingR = returnJson =<< runDB . insertEntity =<< (requireCheckJsonBody :: Handler Reference)
diff --git a/Handler/UpdateItem.hs b/Handler/UpdateItem.hs
index 353572b..a4a29c2 100644
--- a/Handler/UpdateItem.hs
+++ b/Handler/UpdateItem.hs
@@ -6,28 +6,28 @@ import Handler.Common
6 6
7getUpdateItemR, postUpdateItemR :: ItemId -> Handler TypedContent 7getUpdateItemR, postUpdateItemR :: ItemId -> Handler TypedContent
8getUpdateItemR = postUpdateItemR 8getUpdateItemR = postUpdateItemR
9postUpdateItemR fsUpdateItem = do 9postUpdateItemR fsUpdateId = do
10 Just entity <- fmap (Entity fsUpdateItem) <$> runDB (get fsUpdateItem) 10 Just entity <- fmap (Entity fsUpdateId) <$> runDB (get fsUpdateId)
11 11
12 ((updateResult, fsUpdateForm), fsUpdateEncoding) <- runFormPost . itemForm . Just $ entityVal entity 12 ((updateResult, fsUpdateForm), fsUpdateEncoding) <- runFormPost . itemForm . Just $ entityVal entity
13 13
14 mapM_ (addMessage "formError" . toHtml) =<< case updateResult of 14 mapM_ (addMessage "formError" . toHtml) =<< case updateResult of
15 FormSuccess Item{..} -> [] <$ runDB (update fsUpdateItem [ ItemKind =. itemKind 15 FormSuccess Item{..} -> [] <$ runDB (update fsUpdateId [ ItemKind =. itemKind
16 , ItemNormKind =. normalizeKind itemKind 16 , ItemNormKind =. normalizeKind itemKind
17 , ItemBought =. itemBought 17 , ItemBought =. itemBought
18 , ItemExpires =. itemExpires 18 , ItemExpires =. itemExpires
19 , ItemOpened =. itemOpened 19 , ItemOpened =. itemOpened
20 ]) 20 ])
21 FormFailure errors -> return errors 21 FormFailure errors -> return errors
22 _ -> return [] 22 _ -> return []
23 23
24 selectRep $ do 24 selectRep $ do
25 provideRep $ case updateResult of 25 provideRep $ case updateResult of
26 FormSuccess _ -> redirect $ InventoryListingR :#: fsUpdateItem :: Handler Html 26 FormSuccess _ -> redirect $ InventoryListingR :#: fsUpdateId :: Handler Html
27 _ -> do 27 _ -> do
28 (sortOn entityVal -> stock) <- runDB $ selectList [] [] 28 (sortOn entityVal -> stock) <- runDB $ selectList [] []
29 defaultLayout $ inventoryListing InventoryState 29 defaultLayout $ inventoryListing InventoryState
30 { formState = Just UpdateForm{..} 30 { invFormState = Just UpdateForm{..}
31 , .. 31 , ..
32 } 32 }
33 provideJson () 33 provideJson ()