diff options
| author | Gregor Kleen <gkleen@yggdrasil.li> | 2017-03-14 01:23:09 +0100 |
|---|---|---|
| committer | Gregor Kleen <gkleen@yggdrasil.li> | 2017-03-14 01:23:09 +0100 |
| commit | 47f54fc6d1f081c9fe7ac3d0bee705b3a78609d5 (patch) | |
| tree | ac942d6b57a007a57906c1a8b13c63907c5f2ee7 | |
| parent | 3490d0dac52f79478fdb8db84106a505926e760f (diff) | |
| download | nixos-47f54fc6d1f081c9fe7ac3d0bee705b3a78609d5.tar nixos-47f54fc6d1f081c9fe7ac3d0bee705b3a78609d5.tar.gz nixos-47f54fc6d1f081c9fe7ac3d0bee705b3a78609d5.tar.bz2 nixos-47f54fc6d1f081c9fe7ac3d0bee705b3a78609d5.tar.xz nixos-47f54fc6d1f081c9fe7ac3d0bee705b3a78609d5.zip | |
Switch to bar in repo
| -rw-r--r-- | .gitignore | 4 | ||||
| -rw-r--r-- | bragi.nix | 4 | ||||
| -rwxr-xr-x | bragi/bar.hs | 462 | ||||
| -rw-r--r-- | bragi/bar/default.nix | 30 | ||||
| -rw-r--r-- | bragi/bar/generated.nix | 34 | ||||
| -rw-r--r-- | bragi/bar/generated.nix.gup | 5 |
6 files changed, 75 insertions, 464 deletions
| @@ -1,3 +1,5 @@ | |||
| 1 | configuration.nix | 1 | configuration.nix |
| 2 | config.nix | 2 | config.nix |
| 3 | **/\#*\# \ No newline at end of file | 3 | **/\#*\# |
| 4 | **/.gup/ | ||
| 5 | **/result | ||
| @@ -315,7 +315,9 @@ in rec { | |||
| 315 | wantedBy = [ "default.target" ]; | 315 | wantedBy = [ "default.target" ]; |
| 316 | serviceConfig = { | 316 | serviceConfig = { |
| 317 | Type = "simple"; | 317 | Type = "simple"; |
| 318 | ExecStart = "${ghc}/bin/runghc ${./bragi/bar.hs}"; | 318 | ExecStart = '' |
| 319 | ${pkgs.callPackage ./bragi/bar {}}/bin/bar | ||
| 320 | ''; | ||
| 319 | User = users.extraUsers."bar".name; | 321 | User = users.extraUsers."bar".name; |
| 320 | Group = users.extraUsers."bar".group; | 322 | Group = users.extraUsers."bar".group; |
| 321 | WorkingDirectory = "~"; | 323 | WorkingDirectory = "~"; |
diff --git a/bragi/bar.hs b/bragi/bar.hs deleted file mode 100755 index 826593e7..00000000 --- a/bragi/bar.hs +++ /dev/null | |||
| @@ -1,462 +0,0 @@ | |||
| 1 | #! /usr/bin/env nix-shell | ||
| 2 | #! nix-shell -i runghc -p "haskellPackages.ghcWithPackages (p: with p; [ yesod persistent-postgresql ])" | ||
| 3 | |||
| 4 | |||
| 5 | {-# LANGUAGE RecordWildCards #-} | ||
| 6 | {-# LANGUAGE FlexibleContexts #-} | ||
| 7 | {-# LANGUAGE GADTs #-} | ||
| 8 | {-# LANGUAGE GeneralizedNewtypeDeriving #-} | ||
| 9 | {-# LANGUAGE MultiParamTypeClasses #-} | ||
| 10 | {-# LANGUAGE OverloadedStrings #-} | ||
| 11 | {-# LANGUAGE QuasiQuotes #-} | ||
| 12 | {-# LANGUAGE TemplateHaskell #-} | ||
| 13 | {-# LANGUAGE TypeFamilies #-} | ||
| 14 | {-# LANGUAGE FlexibleInstances #-} | ||
| 15 | {-# LANGUAGE ViewPatterns #-} | ||
| 16 | {-# LANGUAGE TupleSections #-} | ||
| 17 | {-# LANGUAGE ApplicativeDo #-} | ||
| 18 | |||
| 19 | |||
| 20 | import Yesod | ||
| 21 | import Database.Persist.Postgresql | ||
| 22 | import Network.Wai (requestHeaders) | ||
| 23 | |||
| 24 | import Control.Monad.Logger (runStderrLoggingT) | ||
| 25 | import Control.Monad.Reader | ||
| 26 | import Control.Monad.Writer | ||
| 27 | import Control.Monad.Trans.Maybe | ||
| 28 | |||
| 29 | import Data.Time.Clock | ||
| 30 | import Data.Time.Calendar | ||
| 31 | import Data.Time.Format | ||
| 32 | |||
| 33 | import Data.Text (Text) | ||
| 34 | import qualified Data.Text as Text | ||
| 35 | |||
| 36 | import qualified Data.Text.Encoding as TE | ||
| 37 | import qualified Data.Text.Encoding.Error as TEE | ||
| 38 | |||
| 39 | import Data.Map.Lazy (Map) | ||
| 40 | import qualified Data.Map.Lazy as Map | ||
| 41 | |||
| 42 | import Data.Set (Set) | ||
| 43 | import qualified Data.Set as Set | ||
| 44 | |||
| 45 | import Data.Aeson | ||
| 46 | import Data.Traversable | ||
| 47 | import Data.Maybe | ||
| 48 | import Data.Bool | ||
| 49 | import Data.String (IsString(..)) | ||
| 50 | import Data.Unique | ||
| 51 | import Data.List (sortOn) | ||
| 52 | import Data.Ord | ||
| 53 | |||
| 54 | |||
| 55 | share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase| | ||
| 56 | Item | ||
| 57 | kind Text | ||
| 58 | bought Day Maybe | ||
| 59 | expires Day Maybe | ||
| 60 | opened Day Maybe | ||
| 61 | deriving Show Eq | ||
| 62 | |] | ||
| 63 | |||
| 64 | instance Ord Item where | ||
| 65 | x `compare` y = mconcat | ||
| 66 | [ (isNothing $ itemOpened x) `compare` (isNothing $ itemOpened y) | ||
| 67 | , itemOpened x `compare` itemOpened y | ||
| 68 | , (isNothing $ itemExpires x) `compare` (isNothing $ itemExpires y) | ||
| 69 | , itemExpires x `compare` itemExpires x | ||
| 70 | , itemKind x `compare` itemKind x | ||
| 71 | , itemBought x `compare` itemBought x | ||
| 72 | ] | ||
| 73 | |||
| 74 | instance ToJSON Item where | ||
| 75 | toJSON Item{..} = object $ | ||
| 76 | [ "kind" .= itemKind | ||
| 77 | ] ++ maybe [] (\x -> ["bought" .= x]) itemBought | ||
| 78 | ++ maybe [] (\x -> ["expires" .= x]) itemExpires | ||
| 79 | ++ maybe [] (\x -> ["opened" .= x]) itemOpened | ||
| 80 | |||
| 81 | instance FromJSON Item where | ||
| 82 | parseJSON = withObject "Item" $ \obj -> do | ||
| 83 | itemKind <- obj .: "kind" | ||
| 84 | itemBought <- obj .:? "bought" | ||
| 85 | itemExpires <- obj .:? "expires" | ||
| 86 | itemOpened <- obj .:? "opened" | ||
| 87 | return Item{..} | ||
| 88 | |||
| 89 | instance ToJSON (Entity Item) where | ||
| 90 | toJSON = entityIdToJSON | ||
| 91 | |||
| 92 | instance FromJSON (Entity Item) where | ||
| 93 | parseJSON = entityIdFromJSON | ||
| 94 | |||
| 95 | data ItemDiff = DiffKind Text | ||
| 96 | | DiffBought (Maybe Day) | ||
| 97 | | DiffExpires (Maybe Day) | ||
| 98 | | DiffOpened (Maybe Day) | ||
| 99 | |||
| 100 | newtype ItemDiffs = ItemDiffs [ItemDiff] | ||
| 101 | |||
| 102 | instance FromJSON ItemDiffs where | ||
| 103 | parseJSON = withObject "ItemDiff" $ \obj -> fmap ItemDiffs . execWriterT $ do | ||
| 104 | tell =<< maybe [] (pure . DiffKind) <$> lift (obj .:? "kind") | ||
| 105 | tell =<< maybe [] (pure . DiffBought) <$> lift (obj .:! "bought") | ||
| 106 | tell =<< maybe [] (pure . DiffExpires) <$> lift (obj .:! "expires") | ||
| 107 | tell =<< maybe [] (pure . DiffOpened) <$> lift (obj .:! "opened") | ||
| 108 | |||
| 109 | toUpdate :: ItemDiffs -> [Update Item] | ||
| 110 | toUpdate (ItemDiffs ds) = do | ||
| 111 | x <- ds | ||
| 112 | return $ case x of | ||
| 113 | DiffKind t -> ItemKind =. t | ||
| 114 | DiffBought d -> ItemBought =. d | ||
| 115 | DiffExpires d -> ItemExpires =. d | ||
| 116 | DiffOpened d -> ItemOpened =. d | ||
| 117 | |||
| 118 | |||
| 119 | data BarInventory = BarInventory | ||
| 120 | { sqlPool :: ConnectionPool | ||
| 121 | } | ||
| 122 | |||
| 123 | mkYesod "BarInventory" [parseRoutes| | ||
| 124 | / InventoryR GET PUT POST | ||
| 125 | /#ItemId ItemR GET PUT PATCH DELETE | ||
| 126 | /#ItemId/open OpenItemR POST | ||
| 127 | /#ItemId/update UpdateItemR POST GET | ||
| 128 | /#ItemId/delete DeleteItemR POST | ||
| 129 | |] | ||
| 130 | |||
| 131 | instance Yesod BarInventory where | ||
| 132 | approot = ApprootRequest $ \_ req -> maybe "" (TE.decodeUtf8With TEE.lenientDecode) $ Map.lookup "AppRoot" (Map.fromList $ requestHeaders req) | ||
| 133 | |||
| 134 | instance RenderMessage BarInventory FormMessage where | ||
| 135 | renderMessage _ _ = defaultFormMessage | ||
| 136 | |||
| 137 | instance YesodPersist BarInventory where | ||
| 138 | type YesodPersistBackend BarInventory = SqlBackend | ||
| 139 | |||
| 140 | runDB action = runSqlPool action . sqlPool =<< getYesod | ||
| 141 | |||
| 142 | |||
| 143 | data ViewState = ViewState | ||
| 144 | { errs :: [Text] | ||
| 145 | , insertForm :: Maybe Widget | ||
| 146 | , insertEncoding :: Maybe Enctype | ||
| 147 | , stock :: [Entity Item] | ||
| 148 | , updateItem :: Maybe ItemId | ||
| 149 | , updateForm :: Maybe Widget | ||
| 150 | , updateEncoding :: Maybe Enctype | ||
| 151 | } | ||
| 152 | |||
| 153 | |||
| 154 | |||
| 155 | main = runStderrLoggingT . withPostgresqlPool "user=bar dbname=bar" 5 . runReaderT $ do | ||
| 156 | sqlPool <- ask | ||
| 157 | mapM_ ($(logWarnS) "DB") =<< runSqlPool (runMigrationSilent migrateAll) sqlPool | ||
| 158 | liftIO . warpEnv $ BarInventory{..} | ||
| 159 | |||
| 160 | |||
| 161 | itemFragment itemId = "item" <> show (fromSqlKey itemId) | ||
| 162 | |||
| 163 | itemForm :: Maybe Item -> Html -> MForm Handler (FormResult Item, Widget) | ||
| 164 | itemForm proto identView = do | ||
| 165 | today <- utctDay <$> liftIO getCurrentTime | ||
| 166 | |||
| 167 | (kindRes, kindView) <- mreq textField "" $ itemKind <$> proto | ||
| 168 | (boughtRes, boughtWidget) <- dayForm (maybe (Just $ Just today) Just $ fmap itemBought proto) "Unknown" | ||
| 169 | (expiresRes, expiresWidget) <- dayForm (fmap itemExpires proto) "Never" | ||
| 170 | (openedRes, openedWidget) <- dayForm (fmap itemOpened proto) "Never" | ||
| 171 | |||
| 172 | let itemRes = do | ||
| 173 | itemKind <- kindRes | ||
| 174 | itemBought <- boughtRes | ||
| 175 | itemExpires <- expiresRes | ||
| 176 | itemOpened <- openedRes | ||
| 177 | return Item{..} | ||
| 178 | |||
| 179 | return . (itemRes, ) $ do | ||
| 180 | toWidget | ||
| 181 | [cassius| | ||
| 182 | label.checkbox | ||
| 183 | input | ||
| 184 | vertical-align: middle | ||
| 185 | span | ||
| 186 | vertical-align: middle | ||
| 187 | |] | ||
| 188 | -- addScriptRemote "https://cdn.jsdelivr.net/webshim/1.16.0/extras/modernizr-custom.js" | ||
| 189 | addScriptRemote "https://cdn.jsdelivr.net/webshim/1.16.0/polyfiller.js" | ||
| 190 | addScriptRemote "https://cdn.jsdelivr.net/jquery/3.1.1/jquery.js" | ||
| 191 | toWidget | ||
| 192 | [julius| | ||
| 193 | webshims.setOptions("forms-ext", { | ||
| 194 | "widgets": { | ||
| 195 | "classes": "hide-dropdownbtn" | ||
| 196 | } | ||
| 197 | }); | ||
| 198 | webshims.activeLang("en-GB"); | ||
| 199 | webshims.polyfill("forms forms-ext"); | ||
| 200 | |] | ||
| 201 | [whamlet| | ||
| 202 | #{identView} | ||
| 203 | <div .td>^{fvInput kindView} | ||
| 204 | <div .td>^{boughtWidget} | ||
| 205 | <div .td>^{expiresWidget} | ||
| 206 | <div .td>^{openedWidget} | ||
| 207 | |] | ||
| 208 | where | ||
| 209 | dayForm :: Maybe (Maybe Day) -> String -> MForm Handler (FormResult (Maybe Day), Widget) | ||
| 210 | dayForm proto label = do | ||
| 211 | today <- utctDay <$> liftIO getCurrentTime | ||
| 212 | |||
| 213 | checkboxId <- ("check" <>) . show . hashUnique <$> liftIO newUnique | ||
| 214 | |||
| 215 | (fmap (fromMaybe False) -> isNothingRes, isNothingView) <- | ||
| 216 | mopt checkBoxField ("" { fsId = Just $ Text.pack checkboxId }) . Just . Just . fromMaybe True $ fmap isNothing proto | ||
| 217 | (dayRes, dayView) <- | ||
| 218 | mreq dayField "" . Just . fromMaybe today $ join proto | ||
| 219 | |||
| 220 | let res = (bool Just (const Nothing) <$> isNothingRes) <*> dayRes | ||
| 221 | return . (res, ) $ do | ||
| 222 | [whamlet| | ||
| 223 | $newline never | ||
| 224 | <div .table> | ||
| 225 | <div .tr> | ||
| 226 | <label for=#{checkboxId} .checkbox .td> | ||
| 227 | ^{fvInput isNothingView} | ||
| 228 | <span> | ||
| 229 | #{label} | ||
| 230 | <div .tr> | ||
| 231 | <div .td .dayInput>^{fvInput dayView} | ||
| 232 | |] | ||
| 233 | |||
| 234 | |||
| 235 | |||
| 236 | getInventoryR, postInventoryR :: Handler TypedContent | ||
| 237 | postInventoryR = getInventoryR | ||
| 238 | getInventoryR = do | ||
| 239 | ((insertResult, (Just -> insertForm)), (Just -> insertEncoding)) <- runFormPost $ itemForm Nothing | ||
| 240 | |||
| 241 | errs <- case insertResult of | ||
| 242 | FormSuccess newItem -> [] <$ runDB (insert newItem) | ||
| 243 | FormFailure errors -> return errors | ||
| 244 | _ -> return [] | ||
| 245 | |||
| 246 | (sortOn entityVal -> stock) <- runDB $ selectList [] [] | ||
| 247 | |||
| 248 | selectRep $ do | ||
| 249 | provideJson (stock :: [Entity Item]) | ||
| 250 | provideRep $ mainView ViewState | ||
| 251 | { updateItem = Nothing | ||
| 252 | , updateForm = Nothing | ||
| 253 | , updateEncoding = Nothing | ||
| 254 | , .. | ||
| 255 | } | ||
| 256 | |||
| 257 | postUpdateItemR, getUpdateItemR :: ItemId -> Handler TypedContent | ||
| 258 | postUpdateItemR = getUpdateItemR | ||
| 259 | getUpdateItemR updateItem = do | ||
| 260 | Just entity <- fmap (Entity updateItem) <$> runDB (get updateItem) | ||
| 261 | |||
| 262 | ((updateResult, (Just -> updateForm)), (Just -> updateEncoding)) <- runFormPost . itemForm . Just $ entityVal entity | ||
| 263 | |||
| 264 | errs <- case updateResult of | ||
| 265 | FormSuccess Item{..} -> [] <$ runDB (update updateItem [ ItemKind =. itemKind | ||
| 266 | , ItemBought =. itemBought | ||
| 267 | , ItemExpires =. itemExpires | ||
| 268 | , ItemOpened =. itemOpened | ||
| 269 | ]) | ||
| 270 | FormFailure errors -> return errors | ||
| 271 | _ -> return [] | ||
| 272 | |||
| 273 | selectRep $ do | ||
| 274 | provideRep $ case updateResult of | ||
| 275 | FormSuccess _ -> redirect $ InventoryR :#: itemFragment updateItem :: Handler Html | ||
| 276 | _ -> do | ||
| 277 | (sortOn entityVal -> stock) <- runDB $ selectList [] [] | ||
| 278 | mainView ViewState | ||
| 279 | { insertForm = Nothing | ||
| 280 | , insertEncoding = Nothing | ||
| 281 | , updateItem = Just updateItem | ||
| 282 | , .. | ||
| 283 | } | ||
| 284 | provideJson () | ||
| 285 | |||
| 286 | mainView :: ViewState -> Handler Html | ||
| 287 | mainView ViewState{..} = defaultLayout $ do | ||
| 288 | let | ||
| 289 | dayFormat = formatTime defaultTimeLocale "%e. %b %y" | ||
| 290 | |||
| 291 | setTitle "Bar Inventory" | ||
| 292 | toWidget | ||
| 293 | [cassius| | ||
| 294 | .table | ||
| 295 | display: table | ||
| 296 | .table div | ||
| 297 | vertical-align: middle | ||
| 298 | .td | ||
| 299 | display: table-cell | ||
| 300 | text-align: center | ||
| 301 | padding: 0.25em | ||
| 302 | .tr | ||
| 303 | display: table-row | ||
| 304 | .tc | ||
| 305 | display: table-caption | ||
| 306 | padding: 0.25em | ||
| 307 | .th | ||
| 308 | display: table-cell | ||
| 309 | font-variant: small-caps | ||
| 310 | font-weight: bold | ||
| 311 | text-align: center | ||
| 312 | padding: 0.25em | ||
| 313 | .kind | ||
| 314 | display: table-cell | ||
| 315 | text-align: left | ||
| 316 | padding: 0.25em | ||
| 317 | .table .table .td, .table .table .tc, .table .table .th, .table .table .kind | ||
| 318 | padding: 0 | ||
| 319 | .error | ||
| 320 | background-color: #fdd | ||
| 321 | text-align: center | ||
| 322 | color: #c00 | ||
| 323 | list-style-type: none | ||
| 324 | button | ||
| 325 | width: 6em | ||
| 326 | display:inline-text | ||
| 327 | .day hr | ||
| 328 | width: 2em | ||
| 329 | border: 1px solid #ddd | ||
| 330 | border-style: solid none solid none | ||
| 331 | .sepBelow > div, .sepAbove > div | ||
| 332 | border: 2px none #ddd | ||
| 333 | .sepBelow > div | ||
| 334 | border-bottom-style: solid | ||
| 335 | .sepAbove > div | ||
| 336 | border-top-style: solid | ||
| 337 | .color:nth-child(even) | ||
| 338 | background-color: #f0f0f0 | ||
| 339 | .color:nth-child(odd) | ||
| 340 | background-color: #fff | ||
| 341 | body > div | ||
| 342 | margin: 0 auto | ||
| 343 | .table > h1 | ||
| 344 | display: table-caption | ||
| 345 | h1 | ||
| 346 | font-size: 1.5em | ||
| 347 | font-weight: bold | ||
| 348 | font-variant: small-caps | ||
| 349 | text-align: center | ||
| 350 | margin:0 0 .5em 0 | ||
| 351 | |] | ||
| 352 | toWidget | ||
| 353 | [whamlet| | ||
| 354 | <div .table> | ||
| 355 | <h1> | ||
| 356 | Inventory | ||
| 357 | $if not $ null errs | ||
| 358 | <ul .tc .error .sepBelow> | ||
| 359 | $forall e <- errs | ||
| 360 | <li>#{e} | ||
| 361 | <div .tr .sepBelow> | ||
| 362 | <div .th>Description | ||
| 363 | <div .th>Bought | ||
| 364 | <div .th>Expires | ||
| 365 | <div .th>Opened | ||
| 366 | <div .th>Actions | ||
| 367 | $maybe insertEncoding <- insertEncoding | ||
| 368 | $maybe insertForm <- insertForm | ||
| 369 | <form .tr .sepBelow action=@{InventoryR} method=post enctype=#{insertEncoding}> | ||
| 370 | ^{insertForm} | ||
| 371 | <div .td> | ||
| 372 | <button type=submit> | ||
| 373 | Insert | ||
| 374 | $forall e@(Entity itemId Item{..}) <- stock | ||
| 375 | $with idN <- fromSqlKey itemId | ||
| 376 | $if and [ Just itemId == updateItem, isJust updateEncoding, isJust updateForm ] | ||
| 377 | $maybe updateEncoding <- updateEncoding | ||
| 378 | $maybe updateForm <- updateForm | ||
| 379 | <form .tr .color action=@{UpdateItemR itemId}##{itemFragment itemId} method=post enctype=#{updateEncoding} ##{itemFragment itemId}> | ||
| 380 | ^{updateForm} | ||
| 381 | <div .td> | ||
| 382 | <button type=submit> | ||
| 383 | Save Changes | ||
| 384 | $else | ||
| 385 | <div .tr .color ##{itemFragment itemId}> | ||
| 386 | <div .kind>#{itemKind} | ||
| 387 | <div .td .day> | ||
| 388 | $maybe bought <- itemBought | ||
| 389 | #{dayFormat bought} | ||
| 390 | $nothing | ||
| 391 | <hr> | ||
| 392 | <div .td .day> | ||
| 393 | $maybe expires <- itemExpires | ||
| 394 | #{dayFormat expires} | ||
| 395 | $nothing | ||
| 396 | <hr> | ||
| 397 | <div .td .day> | ||
| 398 | $maybe opened <- itemOpened | ||
| 399 | #{dayFormat opened} | ||
| 400 | $nothing | ||
| 401 | <form method=post action=@{OpenItemR itemId}> | ||
| 402 | <button type=submit> | ||
| 403 | Open | ||
| 404 | <div .td> | ||
| 405 | <form method=get action=@{UpdateItemR itemId}##{itemFragment itemId}> | ||
| 406 | <button type=submit> | ||
| 407 | Edit | ||
| 408 | <form method=post action=@{DeleteItemR itemId}> | ||
| 409 | <button type=submit> | ||
| 410 | Delete | ||
| 411 | |] | ||
| 412 | |||
| 413 | putInventoryR :: Handler Value | ||
| 414 | putInventoryR = returnJson =<< runDB . insertEntity =<< (requireCheckJsonBody :: Handler Item) | ||
| 415 | |||
| 416 | getItemR :: ItemId -> Handler TypedContent | ||
| 417 | getItemR itemId = do | ||
| 418 | let getEntity id = fmap (Entity id) <$> get id | ||
| 419 | |||
| 420 | eLookup <- runDB $ getEntity itemId | ||
| 421 | |||
| 422 | case eLookup of | ||
| 423 | Nothing -> notFound | ||
| 424 | Just entity -> do | ||
| 425 | |||
| 426 | selectRep $ do | ||
| 427 | provideJson entity | ||
| 428 | provideRep (redirect $ UpdateItemR itemId :#: itemFragment itemId :: Handler Html) | ||
| 429 | |||
| 430 | patchItemR :: ItemId -> Handler Value | ||
| 431 | patchItemR itemId = do | ||
| 432 | diffs <- (requireCheckJsonBody :: Handler ItemDiffs) | ||
| 433 | returnJson . Entity itemId =<< runDB (updateGet itemId $ toUpdate diffs) | ||
| 434 | |||
| 435 | putItemR :: ItemId -> Handler Value | ||
| 436 | putItemR itemId = do | ||
| 437 | Item{..} <- requireCheckJsonBody | ||
| 438 | returnJson . Entity itemId =<< runDB | ||
| 439 | (updateGet itemId [ ItemKind =. itemKind | ||
| 440 | , ItemBought =. itemBought | ||
| 441 | , ItemExpires =. itemExpires | ||
| 442 | , ItemOpened =. itemOpened | ||
| 443 | ]) | ||
| 444 | |||
| 445 | deleteItemR :: ItemId -> Handler () | ||
| 446 | deleteItemR = runDB . delete | ||
| 447 | |||
| 448 | postDeleteItemR :: ItemId -> Handler TypedContent | ||
| 449 | postDeleteItemR itemId = do | ||
| 450 | runDB $ delete itemId | ||
| 451 | selectRep $ do | ||
| 452 | provideJson () | ||
| 453 | provideRep (redirect $ InventoryR :: Handler Html) | ||
| 454 | |||
| 455 | postOpenItemR :: ItemId -> Handler TypedContent | ||
| 456 | postOpenItemR itemId = do | ||
| 457 | today <- utctDay <$> liftIO getCurrentTime | ||
| 458 | result <- fmap (Entity itemId) . runDB $ updateGet itemId [ ItemOpened =. Just today | ||
| 459 | ] | ||
| 460 | selectRep $ do | ||
| 461 | provideJson result | ||
| 462 | provideRep (redirect $ InventoryR :#: itemFragment itemId :: Handler Html) | ||
diff --git a/bragi/bar/default.nix b/bragi/bar/default.nix new file mode 100644 index 00000000..fd5e7acf --- /dev/null +++ b/bragi/bar/default.nix | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | { haskellPackages | ||
| 2 | , stdenv | ||
| 3 | , fetchFromGitHub | ||
| 4 | , jquery | ||
| 5 | }: | ||
| 6 | |||
| 7 | let | ||
| 8 | pkg = haskellPackages.callPackage ./generated.nix {}; | ||
| 9 | webshim = stdenv.mkDerivation rec { | ||
| 10 | name = "webshim-${version}"; | ||
| 11 | version = "1.16.0"; | ||
| 12 | src = fetchFromGitHub { | ||
| 13 | owner = "aFarkas"; | ||
| 14 | repo = "webshim"; | ||
| 15 | rev = "1.16.0"; | ||
| 16 | sha256 = "14pk7hljqipzp0n7vpgcfxr3w4bla57cwyd7bmwmmxrm2zn62cyh"; | ||
| 17 | }; | ||
| 18 | |||
| 19 | installPhase = '' | ||
| 20 | mkdir -p $out/js | ||
| 21 | cp -r $src/js-webshim/dev/* $out/js/ | ||
| 22 | ''; | ||
| 23 | }; | ||
| 24 | in stdenv.lib.overrideDerivation pkg (drv: { | ||
| 25 | postUnpack = '' | ||
| 26 | rm -rf bar/static/jquery.js bar/static/webshim | ||
| 27 | ln -vs ${jquery}/js/jquery.js bar/static | ||
| 28 | ln -vs ${webshim}/js bar/static/webshim | ||
| 29 | ''; | ||
| 30 | }) | ||
diff --git a/bragi/bar/generated.nix b/bragi/bar/generated.nix new file mode 100644 index 00000000..4243ad4d --- /dev/null +++ b/bragi/bar/generated.nix | |||
| @@ -0,0 +1,34 @@ | |||
| 1 | { mkDerivation, aeson, base, bytestring, case-insensitive | ||
| 2 | , classy-prelude, classy-prelude-conduit, classy-prelude-yesod | ||
| 3 | , conduit, containers, data-default, directory, fast-logger | ||
| 4 | , fetchgit, file-embed, hjsmin, http-conduit, lens, monad-control | ||
| 5 | , monad-logger, mtl, persistent, persistent-postgresql | ||
| 6 | , persistent-template, safe, shakespeare, stdenv, template-haskell | ||
| 7 | , text, time, unordered-containers, vector, wai, wai-extra | ||
| 8 | , wai-logger, warp, yaml, yesod, yesod-auth, yesod-core, yesod-form | ||
| 9 | , yesod-static | ||
| 10 | }: | ||
| 11 | mkDerivation { | ||
| 12 | pname = "bar"; | ||
| 13 | version = "0.0.0"; | ||
| 14 | src = fetchgit { | ||
| 15 | url = "git://git.yggdrasil.li/gkleen/pub/bar"; | ||
| 16 | sha256 = "13h5hxwx4y79jr19l894zq4ynvkmhfds52xm8dlsdl5j69gg7laa"; | ||
| 17 | rev = "53fcf55c02f9335518c28d26429913258fc28f87"; | ||
| 18 | }; | ||
| 19 | isLibrary = true; | ||
| 20 | isExecutable = true; | ||
| 21 | libraryHaskellDepends = [ | ||
| 22 | aeson base bytestring case-insensitive classy-prelude | ||
| 23 | classy-prelude-conduit classy-prelude-yesod conduit containers | ||
| 24 | data-default directory fast-logger file-embed hjsmin http-conduit | ||
| 25 | lens monad-control monad-logger mtl persistent | ||
| 26 | persistent-postgresql persistent-template safe shakespeare | ||
| 27 | template-haskell text time unordered-containers vector wai | ||
| 28 | wai-extra wai-logger warp yaml yesod yesod-auth yesod-core | ||
| 29 | yesod-form yesod-static | ||
| 30 | ]; | ||
| 31 | executableHaskellDepends = [ base ]; | ||
| 32 | doHaddock = false; | ||
| 33 | license = stdenv.lib.licenses.unfree; | ||
| 34 | } | ||
diff --git a/bragi/bar/generated.nix.gup b/bragi/bar/generated.nix.gup new file mode 100644 index 00000000..eeb13ad2 --- /dev/null +++ b/bragi/bar/generated.nix.gup | |||
| @@ -0,0 +1,5 @@ | |||
| 1 | #!/usr/bin/env zsh | ||
| 2 | |||
| 3 | gup -u ${2:r}.cabal | ||
| 4 | cd ${2:h} | ||
| 5 | cabal2nix --no-haddock "git://git.yggdrasil.li/gkleen/pub/bar" >! ${1} | ||
