74 lines
2.1 KiB
Haskell
74 lines
2.1 KiB
Haskell
{-# OPTIONS -fno-warn-orphans #-}
|
|
|
|
module Utils.Csv
|
|
( typeCsv, typeCsv', extensionCsv
|
|
, pathPieceCsv
|
|
, (.:??)
|
|
, CsvRendered(..)
|
|
, toCsvRendered
|
|
, toDefaultOrderedCsvRendered
|
|
) where
|
|
|
|
import ClassyPrelude hiding (lookup)
|
|
import Settings.Mime
|
|
|
|
import Data.Csv hiding (Name)
|
|
import Data.Csv.Conduit (CsvParseError)
|
|
|
|
import Language.Haskell.TH (Name)
|
|
import Language.Haskell.TH.Lib
|
|
|
|
import Yesod.Core.Content (ContentType, simpleContentType)
|
|
|
|
import qualified Data.Map as Map
|
|
|
|
|
|
deriving instance Typeable CsvParseError
|
|
instance Exception CsvParseError
|
|
|
|
|
|
typeCsv, typeCsv' :: ContentType
|
|
typeCsv = simpleContentType typeCsv'
|
|
typeCsv' = "text/csv; charset=UTF-8; header=present"
|
|
|
|
extensionCsv :: Extension
|
|
extensionCsv = fromMaybe "csv" $ listToMaybe [ ext | (ext, mime) <- Map.toList mimeMap, mime == typeCsv ]
|
|
|
|
|
|
pathPieceCsv :: Name -> DecsQ
|
|
pathPieceCsv (conT -> t) =
|
|
[d|
|
|
instance ToField $(t) where
|
|
toField = toField . toPathPiece
|
|
instance FromField $(t) where
|
|
parseField = maybe (fail "Could not unmarshal from PathPiece") return . fromPathPiece <=< parseField
|
|
|]
|
|
|
|
|
|
(.:??) :: FromField (Maybe a) => NamedRecord -> ByteString -> Parser (Maybe a)
|
|
m .:?? name = lookup m name <|> return Nothing
|
|
|
|
|
|
data CsvRendered = CsvRendered
|
|
{ csvRenderedHeader :: Header
|
|
, csvRenderedData :: [NamedRecord]
|
|
} deriving (Eq, Read, Show, Generic, Typeable)
|
|
|
|
toCsvRendered :: forall mono.
|
|
( ToNamedRecord (Element mono)
|
|
, MonoFoldable mono
|
|
)
|
|
=> Header
|
|
-> mono -> CsvRendered
|
|
toCsvRendered csvRenderedHeader (otoList -> csvs) = CsvRendered{..}
|
|
where
|
|
csvRenderedData = map toNamedRecord csvs
|
|
|
|
toDefaultOrderedCsvRendered :: forall mono.
|
|
( ToNamedRecord (Element mono)
|
|
, DefaultOrdered (Element mono)
|
|
, MonoFoldable mono
|
|
)
|
|
=> mono -> CsvRendered
|
|
toDefaultOrderedCsvRendered = toCsvRendered $ headerOrder (error "headerOrder" :: Element mono)
|