diff options
| author | Gregor Kleen <gkleen@yggdrasil.li> | 2016-02-18 15:04:19 +0100 |
|---|---|---|
| committer | Gregor Kleen <gkleen@yggdrasil.li> | 2016-02-18 15:04:19 +0100 |
| commit | a805783f4bb2868e63ba49a911775fff30df5a07 (patch) | |
| tree | 130c8ef970f9489876d0667eff25444a0816c41a | |
| parent | c88197535f7a4c13b7464a785881a91a67ebd15b (diff) | |
| download | thermoprint-a805783f4bb2868e63ba49a911775fff30df5a07.tar thermoprint-a805783f4bb2868e63ba49a911775fff30df5a07.tar.gz thermoprint-a805783f4bb2868e63ba49a911775fff30df5a07.tar.bz2 thermoprint-a805783f4bb2868e63ba49a911775fff30df5a07.tar.xz thermoprint-a805783f4bb2868e63ba49a911775fff30df5a07.zip | |
Introduced Range
| -rw-r--r-- | client/src/Thermoprint/Client.hs | 7 | ||||
| -rw-r--r-- | server/src/Thermoprint/Server/API.hs | 15 | ||||
| -rw-r--r-- | spec/src/Thermoprint/API.hs | 34 |
3 files changed, 37 insertions, 19 deletions
diff --git a/client/src/Thermoprint/Client.hs b/client/src/Thermoprint/Client.hs index 80045dd..2b99e7e 100644 --- a/client/src/Thermoprint/Client.hs +++ b/client/src/Thermoprint/Client.hs | |||
| @@ -45,10 +45,8 @@ data Client m = Client | |||
| 45 | { printers :: EitherT ServantError m (Map PrinterId PrinterStatus) | 45 | { printers :: EitherT ServantError m (Map PrinterId PrinterStatus) |
| 46 | -- ^ List all printers | 46 | -- ^ List all printers |
| 47 | , jobs :: Maybe PrinterId | 47 | , jobs :: Maybe PrinterId |
| 48 | -> Maybe JobId | 48 | -> Maybe (Range (JobId)) |
| 49 | -> Maybe JobId | 49 | -> Maybe (Range (UTCTime)) |
| 50 | -> Maybe UTCTime | ||
| 51 | -> Maybe UTCTime | ||
| 52 | -> EitherT ServantError m (Seq (JobId, UTCTime, JobStatus)) | 50 | -> EitherT ServantError m (Seq (JobId, UTCTime, JobStatus)) |
| 53 | -- ^ @jobs p minId maxId minTime maxTime@ lists a selection of jobs | 51 | -- ^ @jobs p minId maxId minTime maxTime@ lists a selection of jobs |
| 54 | , jobCreate :: Maybe PrinterId -> Printout -> EitherT ServantError m JobId | 52 | , jobCreate :: Maybe PrinterId -> Printout -> EitherT ServantError m JobId |
| @@ -79,6 +77,7 @@ data Client m = Client | |||
| 79 | } | 77 | } |
| 80 | 78 | ||
| 81 | withArgs :: (x -> a :<|> b) -> ((x -> a) :<|> (x -> b)) | 79 | withArgs :: (x -> a :<|> b) -> ((x -> a) :<|> (x -> b)) |
| 80 | -- ^ Undo factoring of APIs | ||
| 82 | withArgs subAPI = (\(a :<|> _) -> a) . subAPI :<|> (\(_ :<|> b) -> b) . subAPI | 81 | withArgs subAPI = (\(a :<|> _) -> a) . subAPI :<|> (\(_ :<|> b) -> b) . subAPI |
| 83 | 82 | ||
| 84 | mkClient :: (IO :~> m) -- ^ A monad functor ('Nat') used to make the api functions work in any monad which can be constructed from 'IO' | 83 | mkClient :: (IO :~> m) -- ^ A monad functor ('Nat') used to make the api functions work in any monad which can be constructed from 'IO' |
diff --git a/server/src/Thermoprint/Server/API.hs b/server/src/Thermoprint/Server/API.hs index cd4326e..3f3ab46 100644 --- a/server/src/Thermoprint/Server/API.hs +++ b/server/src/Thermoprint/Server/API.hs | |||
| @@ -141,16 +141,13 @@ printerStatus = fmap queueToStatus . queue' . snd <=< lookupPrinter . Just | |||
| 141 | queueToStatus (Queue _ (Just c) _) = Busy . castId $ jobId c | 141 | queueToStatus (Queue _ (Just c) _) = Busy . castId $ jobId c |
| 142 | 142 | ||
| 143 | listJobs :: Maybe PrinterId | 143 | listJobs :: Maybe PrinterId |
| 144 | -> Maybe API.JobId -> Maybe API.JobId | 144 | -> Maybe (Range API.JobId) -> Maybe (Range UTCTime) |
| 145 | -> Maybe UTCTime -> Maybe UTCTime | ||
| 146 | -> Handler (Seq (API.JobId, UTCTime, JobStatus)) | 145 | -> Handler (Seq (API.JobId, UTCTime, JobStatus)) |
| 147 | listJobs Nothing minId maxId minTime maxTime = fmap mconcat . mapM (\pId -> listJobs (Just pId) minId maxId minTime maxTime) =<< asks (Map.keys . printers) | 146 | listJobs Nothing idR timeR = fmap mconcat . mapM (\pId -> listJobs (Just pId) idR timeR) =<< asks (Map.keys . printers) |
| 148 | listJobs pId minId maxId minTime maxTime = fmap (filterJobs . extractJobs) . (\(a, b) -> (,) a <$> queue' b) =<< lookupPrinter pId | 147 | listJobs pId idR timeR = fmap (filterJobs . extractJobs) . (\(a, b) -> (,) a <$> queue' b) =<< lookupPrinter pId |
| 149 | where | 148 | where |
| 150 | filterJobs = Seq.filter (\(id, time, _) -> and ([ maybe True (<= id ) minId | 149 | filterJobs = Seq.filter (\(id, time, _) -> and ([ maybe True (`contains` id) idR |
| 151 | , maybe True (>= id ) maxId | 150 | , maybe True (`contains` time) timeR |
| 152 | , maybe True (<= time) minTime | ||
| 153 | , maybe True (>= time) maxTime | ||
| 154 | ] :: [Bool]) | 151 | ] :: [Bool]) |
| 155 | ) | 152 | ) |
| 156 | 153 | ||
| @@ -158,7 +155,7 @@ getJob :: API.JobId -> Handler Printout | |||
| 158 | getJob jobId = fmap jobContent . maybe (left err404) return =<< runSqlPool (get $ castId jobId) =<< asks sqlPool | 155 | getJob jobId = fmap jobContent . maybe (left err404) return =<< runSqlPool (get $ castId jobId) =<< asks sqlPool |
| 159 | 156 | ||
| 160 | jobStatus :: API.JobId -> Handler JobStatus | 157 | jobStatus :: API.JobId -> Handler JobStatus |
| 161 | jobStatus jobId = maybe (left err404) return . lookup jobId . map (\(id, _, st) -> (id, st)) . toList =<< listJobs Nothing Nothing Nothing Nothing Nothing | 158 | jobStatus jobId = maybe (left err404) return . lookup jobId . map (\(id, _, st) -> (id, st)) . toList =<< listJobs Nothing Nothing Nothing |
| 162 | 159 | ||
| 163 | abortJob :: API.JobId -> Handler () | 160 | abortJob :: API.JobId -> Handler () |
| 164 | abortJob needle = do | 161 | abortJob needle = do |
diff --git a/spec/src/Thermoprint/API.hs b/spec/src/Thermoprint/API.hs index d854e73..5bfe431 100644 --- a/spec/src/Thermoprint/API.hs +++ b/spec/src/Thermoprint/API.hs | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | {-# LANGUAGE TypeOperators, DataKinds #-} | 2 | {-# LANGUAGE TypeOperators, DataKinds #-} |
| 3 | {-# LANGUAGE StandaloneDeriving #-} | 3 | {-# LANGUAGE StandaloneDeriving #-} |
| 4 | {-# LANGUAGE OverloadedStrings #-} | 4 | {-# LANGUAGE OverloadedStrings #-} |
| 5 | {-# LANGUAGE ViewPatterns #-} | ||
| 5 | 6 | ||
| 6 | -- | A specification of an API for interacting with a set of printers | 7 | -- | A specification of an API for interacting with a set of printers |
| 7 | module Thermoprint.API | 8 | module Thermoprint.API |
| @@ -9,6 +10,7 @@ module Thermoprint.API | |||
| 9 | , JobStatus(..) | 10 | , JobStatus(..) |
| 10 | , PrintingError(..) | 11 | , PrintingError(..) |
| 11 | , DraftTitle | 12 | , DraftTitle |
| 13 | , Range(..), contains | ||
| 12 | , ThermoprintAPI | 14 | , ThermoprintAPI |
| 13 | , thermoprintAPI | 15 | , thermoprintAPI |
| 14 | , module Thermoprint.Identifiers | 16 | , module Thermoprint.Identifiers |
| @@ -21,6 +23,9 @@ import Thermoprint.Identifiers | |||
| 21 | import Servant.API | 23 | import Servant.API |
| 22 | import Data.Aeson | 24 | import Data.Aeson |
| 23 | 25 | ||
| 26 | import Data.Monoid | ||
| 27 | import Data.Maybe | ||
| 28 | |||
| 24 | import Data.Set (Set) | 29 | import Data.Set (Set) |
| 25 | import Data.Map (Map) | 30 | import Data.Map (Map) |
| 26 | import qualified Data.Map as Map (foldMapWithKey, singleton) | 31 | import qualified Data.Map as Map (foldMapWithKey, singleton) |
| @@ -51,7 +56,6 @@ instance (Integral k, Ord k, ToJSON v) => ToJSON (Map k v) where | |||
| 51 | instance (Enum k, Ord k, FromJSON v) => FromJSON (Map k v) where | 56 | instance (Enum k, Ord k, FromJSON v) => FromJSON (Map k v) where |
| 52 | parseJSON = fmap (IntMap.foldMapWithKey $ Map.singleton . castId) . parseJSON | 57 | parseJSON = fmap (IntMap.foldMapWithKey $ Map.singleton . castId) . parseJSON |
| 53 | 58 | ||
| 54 | |||
| 55 | data PrinterStatus = Busy JobId | 59 | data PrinterStatus = Busy JobId |
| 56 | | Available | 60 | | Available |
| 57 | deriving (Generic, Show, FromJSON, ToJSON) | 61 | deriving (Generic, Show, FromJSON, ToJSON) |
| @@ -81,13 +85,31 @@ instance FromText UTCTime where | |||
| 81 | instance ToText UTCTime where | 85 | instance ToText UTCTime where |
| 82 | toText = T.pack . formatTime defaultTimeLocale "%F_%T%Q" | 86 | toText = T.pack . formatTime defaultTimeLocale "%F_%T%Q" |
| 83 | 87 | ||
| 88 | data Range a = Min a | Max a | Through a a | ||
| 89 | |||
| 90 | contains :: Ord a => Range a -> a -> Bool | ||
| 91 | -- ^ Check if a 'Range' contains a point | ||
| 92 | contains (Min min) x = min <= x | ||
| 93 | contains (Max max) x = max >= x | ||
| 94 | contains (Through min max) x = min <= x && x <= max | ||
| 95 | |||
| 96 | instance ToText a => ToText (Range a) where | ||
| 97 | toText (Min min) = toText min <> "-" | ||
| 98 | toText (Max max) = "-" <> toText max | ||
| 99 | toText (Through min max) = toText min <> "-" <> toText max | ||
| 100 | |||
| 101 | instance FromText a => FromText (Range a) where | ||
| 102 | fromText t = listToMaybe $ through <> max <> min | ||
| 103 | where | ||
| 104 | through = [ Through min max | ((fromText -> Just min), (T.uncons -> Just ('-', (fromText -> Just max)))) <- zip (T.inits t) (T.tails t) ] | ||
| 105 | min = [ Min min | (fromText -> Just min) <- T.inits t ] | ||
| 106 | max = [ Max max | (fromText -> Just max) <- T.tails t ] | ||
| 107 | |||
| 84 | type ThermoprintAPI = "printers" :> Get '[JSON] (Map PrinterId PrinterStatus) | 108 | type ThermoprintAPI = "printers" :> Get '[JSON] (Map PrinterId PrinterStatus) |
| 85 | :<|> "jobs" :> ( | 109 | :<|> "jobs" :> ( |
| 86 | QueryParam "printer" PrinterId -- TODO: this is silly, introduce data Range a = Range { rMin :: a, rMax :: a } | 110 | QueryParam "printer" PrinterId |
| 87 | :> QueryParam "min" JobId | 111 | :> QueryParam "jobId" (Range JobId) |
| 88 | :> QueryParam "max" JobId | 112 | :> QueryParam "time" (Range UTCTime) |
| 89 | :> QueryParam "minTime" UTCTime | ||
| 90 | :> QueryParam "maxTime" UTCTime | ||
| 91 | :> Get '[JSON] (Seq (JobId, UTCTime, JobStatus)) | 113 | :> Get '[JSON] (Seq (JobId, UTCTime, JobStatus)) |
| 92 | :<|> QueryParam "printer" PrinterId :> ReqBody '[JSON] Printout :> Post '[JSON] JobId | 114 | :<|> QueryParam "printer" PrinterId :> ReqBody '[JSON] Printout :> Post '[JSON] JobId |
| 93 | ) | 115 | ) |
