-- ldgallery - A static generator which turns a collection of tagged -- pictures into a searchable web gallery. -- -- Copyright (C) 2019 Pacien TRAN-GIRARD -- -- This program is free software: you can redistribute it and/or modify -- it under the terms of the GNU Affero General Public License as -- published by the Free Software Foundation, either version 3 of the -- License, or (at your option) any later version. -- -- This program is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU Affero General Public License for more details. -- -- You should have received a copy of the GNU Affero General Public License -- along with this program. If not, see . {-# LANGUAGE DuplicateRecordFields , DeriveGeneric , DeriveAnyClass #-} module Gallery ( GalleryItem(..), buildGalleryTree ) where import GHC.Generics (Generic) import Data.Char (toLower) import Data.Function ((&)) import Data.Maybe (fromMaybe) import Data.Aeson (ToJSON, genericToJSON, genericToEncoding) import qualified Data.Aeson as JSON import qualified Data.Set as Set import Files import Input import Resource encodingOptions :: JSON.Options encodingOptions = JSON.defaultOptions { JSON.fieldLabelModifier = map toLower , JSON.constructorTagModifier = map toLower , JSON.sumEncoding = JSON.defaultTaggedObject { JSON.tagFieldName = "type" , JSON.contentsFieldName = "contents" } } type ResourcePath = String type Tag = String type FileSizeKB = Int data Resolution = Resolution { width :: Int , height :: Int } deriving (Generic, Show) instance ToJSON Resolution where toJSON = genericToJSON encodingOptions toEncoding = genericToEncoding encodingOptions data GalleryItemProps = Directory { items :: [GalleryItem] } -- | Image { resolution :: Resolution, filesize :: FileSizeKB } -- | Video { filesize :: FileSizeKB } | Unknown deriving (Generic, Show) instance ToJSON GalleryItemProps where toJSON = genericToJSON encodingOptions toEncoding = genericToEncoding encodingOptions -- TODO: fuse GalleryItem and GalleryItemProps data GalleryItem = GalleryItem { title :: String , date :: String -- TODO: checked ISO8601 date , description :: String , tags :: [Tag] , path :: ResourcePath , thumbnail :: Maybe ResourcePath , properties :: GalleryItemProps } deriving (Generic, Show) instance ToJSON GalleryItem where toJSON = genericToJSON encodingOptions toEncoding = genericToEncoding encodingOptions buildGalleryTree :: ResourceTree -> GalleryItem buildGalleryTree (ItemResource sidecar path@(filename:_) thumbnail) = GalleryItem { title = optMeta title filename , date = optMeta date "" -- TODO: check and normalise dates , description = optMeta description "" , tags = optMeta tags [] , path = webPath path , thumbnail = fmap webPath thumbnail , properties = Unknown } -- TODO where optMeta :: (Sidecar -> Maybe a) -> a -> a optMeta get fallback = fromMaybe fallback $ get sidecar buildGalleryTree (DirResource dirItems path@(dirname:_) thumbnail) = map buildGalleryTree dirItems & \items -> GalleryItem { title = dirname -- TODO: consider using the most recent item's date? what if empty? , date = "" -- TODO: consider allowing metadata sidecars for directories too , description = "" , tags = aggregateChildTags items , path = webPath path , thumbnail = fmap webPath thumbnail , properties = Directory items } where aggregateChildTags :: [GalleryItem] -> [Tag] aggregateChildTags = unique . concatMap (\item -> tags (item::GalleryItem)) unique :: Ord a => [a] -> [a] unique = Set.toList . Set.fromList