mirror of
https://code.sup39.dev/repos/Wqawg
synced 2024-12-27 16:44:52 +09:00
Initial incomplete pagination model
This commit is contained in:
parent
5c288c7fdb
commit
117034a8fa
3 changed files with 246 additions and 0 deletions
159
src/Data/Paginate/Local.hs
Normal file
159
src/Data/Paginate/Local.hs
Normal file
|
@ -0,0 +1,159 @@
|
||||||
|
{- This file is part of Vervis.
|
||||||
|
-
|
||||||
|
- Written in 2016 by fr33domlover <fr33domlover@riseup.net>.
|
||||||
|
-
|
||||||
|
- ♡ Copying is an act of love. Please copy, reuse and share.
|
||||||
|
-
|
||||||
|
- The author(s) have dedicated all copyright and related and neighboring
|
||||||
|
- rights to this software to the public domain worldwide. This software is
|
||||||
|
- distributed without any warranty.
|
||||||
|
-
|
||||||
|
- You should have received a copy of the CC0 Public Domain Dedication along
|
||||||
|
- with this software. If not, see
|
||||||
|
- <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||||
|
-}
|
||||||
|
|
||||||
|
module Data.Paginate.Local
|
||||||
|
( -- * Settings
|
||||||
|
-- ** Jump settings
|
||||||
|
JumpSettings ()
|
||||||
|
, jumpMin
|
||||||
|
, jumpFactor
|
||||||
|
, jumpRound
|
||||||
|
-- ** Navigation settings
|
||||||
|
, NavSettings ()
|
||||||
|
, navEdges
|
||||||
|
, navJump
|
||||||
|
, navNext
|
||||||
|
-- ** Pagination settings
|
||||||
|
, PaginateSettings ()
|
||||||
|
, psSelect
|
||||||
|
, psCurrent
|
||||||
|
, psPer
|
||||||
|
-- * Results
|
||||||
|
-- ** Navigation controls
|
||||||
|
, NavModel ()
|
||||||
|
, nmFirst
|
||||||
|
, nmPrevJumps
|
||||||
|
, nmPrev
|
||||||
|
, nmCurrent
|
||||||
|
, nmTotal
|
||||||
|
, nmNext
|
||||||
|
, nmNextJumps
|
||||||
|
, nmLast
|
||||||
|
-- ** Paginate
|
||||||
|
, paginate
|
||||||
|
)
|
||||||
|
where
|
||||||
|
|
||||||
|
import Prelude
|
||||||
|
|
||||||
|
import Data.Default.Class
|
||||||
|
import Data.Ratio
|
||||||
|
|
||||||
|
data JumpSettings = JumpSettings
|
||||||
|
{ -- | Minimal jump size to display. Smaller jumps will be discarded.
|
||||||
|
jumpMin :: Int
|
||||||
|
-- | Ratio of size of consecutive jumps.
|
||||||
|
, jumpFactor :: Ratio Int
|
||||||
|
-- | Round jump page numbers to be multiples of this number. 1 means no
|
||||||
|
-- rounding. 10 means all jumps will be to page numbers that are
|
||||||
|
-- multiples of 10. And so on.
|
||||||
|
, jumpRound :: Int
|
||||||
|
}
|
||||||
|
|
||||||
|
instance Default JumpSettings where
|
||||||
|
def = JumpSettings
|
||||||
|
{ jumpMin = 10
|
||||||
|
, jumpFactor = 2 % 3
|
||||||
|
, jumpRound = 10
|
||||||
|
}
|
||||||
|
|
||||||
|
data NavSettings = NavSettings
|
||||||
|
{ -- | Whether to always show links to first and last pages
|
||||||
|
navEdges :: Bool
|
||||||
|
-- | Whether and how to show jump links
|
||||||
|
, navJump :: Maybe JumpSettings
|
||||||
|
-- | Number of next\/prev page links to show on each side of the current
|
||||||
|
-- page.
|
||||||
|
, navNext :: Int
|
||||||
|
}
|
||||||
|
|
||||||
|
instance Default NavSettings where
|
||||||
|
def = NavSettings
|
||||||
|
{ navEdges = True
|
||||||
|
, navJump = Just def
|
||||||
|
, navNext = 3
|
||||||
|
}
|
||||||
|
|
||||||
|
data PaginateSettings m f i = PaginateSettings
|
||||||
|
{ -- | Get the total number of items being paginated, and given an offset
|
||||||
|
-- and a limit, get the specified subset of the items. The offset tells
|
||||||
|
-- you how many items to skip from the beginning of the list, and then
|
||||||
|
-- the limit says how many items you should take after skipping.
|
||||||
|
psSelect :: Int -> Int -> m (Int, f i)
|
||||||
|
-- | Get the current page
|
||||||
|
, psCurrent :: m Int
|
||||||
|
-- | How many items to list in one page
|
||||||
|
, psPer :: Int
|
||||||
|
}
|
||||||
|
|
||||||
|
instance Monad m => Default (PaginateSettings m f i) where
|
||||||
|
def = PaginateSettings
|
||||||
|
{ psSelect = \ _ _ -> error "You didn't implement psSelect"
|
||||||
|
, psCurrent = return 1
|
||||||
|
, psPer = 30
|
||||||
|
}
|
||||||
|
|
||||||
|
data NavModel = NavModel
|
||||||
|
{
|
||||||
|
nmFirst :: Bool
|
||||||
|
, nmPrevJumps :: [Int]
|
||||||
|
, nmPrev :: [Int]
|
||||||
|
, nmCurrent :: Int
|
||||||
|
, nmTotal :: Int
|
||||||
|
, nmNext :: [Int]
|
||||||
|
, nmNextJumps :: [Int]
|
||||||
|
, nmLast :: Bool
|
||||||
|
}
|
||||||
|
|
||||||
|
-- | Given the number of items per page and the current page number, determine
|
||||||
|
-- the offset and limit.
|
||||||
|
subseq :: Int -> Int -> (Int, Int)
|
||||||
|
subseq per curr =
|
||||||
|
let offset = (curr - 1) * per
|
||||||
|
limit = per
|
||||||
|
in (offset, limit)
|
||||||
|
|
||||||
|
navModel :: NavSettings -> Int -> Int -> NavModel
|
||||||
|
navModel ns curr total = NavModel
|
||||||
|
{ nmFirst = navEdges ns
|
||||||
|
, nmPrevJumps = [] --TODO
|
||||||
|
, nmPrev =
|
||||||
|
if curr == 1 || navNext ns < 1
|
||||||
|
then []
|
||||||
|
else [max 1 (curr - navNext ns) .. curr - 1]
|
||||||
|
, nmCurrent = curr
|
||||||
|
, nmTotal = total
|
||||||
|
, nmNext =
|
||||||
|
if curr >= total || navNext ns < 1
|
||||||
|
then []
|
||||||
|
else [curr + 1 .. min total (curr + navNext ns)]
|
||||||
|
, nmNextJumps = [] --TODO
|
||||||
|
, nmLast = navEdges ns
|
||||||
|
}
|
||||||
|
|
||||||
|
-- | Get a page's contents and its navigation controls.
|
||||||
|
paginate
|
||||||
|
:: Monad m
|
||||||
|
=> PaginateSettings m f i
|
||||||
|
-- ^ How to get the page contents and split them into pages
|
||||||
|
-> NavSettings
|
||||||
|
-- ^ How to build page navigation controls for the user interface
|
||||||
|
-> m (f i, NavModel)
|
||||||
|
-- ^ The items in the current page, and the navigation controls
|
||||||
|
paginate ps ns = do
|
||||||
|
curr <- psCurrent ps
|
||||||
|
let (offset, limit) = subseq (psPer ps) curr
|
||||||
|
(total, items) <- psSelect ps offset limit
|
||||||
|
return (items, navModel ns curr total)
|
82
src/Yesod/Paginate/Local.hs
Normal file
82
src/Yesod/Paginate/Local.hs
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
{- This file is part of Vervis.
|
||||||
|
-
|
||||||
|
- Written in 2016 by fr33domlover <fr33domlover@riseup.net>.
|
||||||
|
-
|
||||||
|
- ♡ Copying is an act of love. Please copy, reuse and share.
|
||||||
|
-
|
||||||
|
- The author(s) have dedicated all copyright and related and neighboring
|
||||||
|
- rights to this software to the public domain worldwide. This software is
|
||||||
|
- distributed without any warranty.
|
||||||
|
-
|
||||||
|
- You should have received a copy of the CC0 Public Domain Dedication along
|
||||||
|
- with this software. If not, see
|
||||||
|
- <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||||
|
-}
|
||||||
|
|
||||||
|
module Yesod.Paginate.Local
|
||||||
|
( -- * Settings
|
||||||
|
NavWidgetSettings ()
|
||||||
|
, nwsFirst
|
||||||
|
, nwsLast
|
||||||
|
, nwsPrev
|
||||||
|
, nwsNext
|
||||||
|
, nwsCurrent
|
||||||
|
-- * Widget
|
||||||
|
, pageNavWidget
|
||||||
|
)
|
||||||
|
where
|
||||||
|
|
||||||
|
import Prelude
|
||||||
|
|
||||||
|
import Data.Default.Class
|
||||||
|
import Data.Text (Text)
|
||||||
|
import Yesod.Core (RenderRoute (..))
|
||||||
|
import Yesod.Core.Widget (WidgetT, whamlet)
|
||||||
|
|
||||||
|
import qualified Formatting as F
|
||||||
|
|
||||||
|
import Data.Paginate.Local
|
||||||
|
|
||||||
|
-- | Settings for building a UI page navigation widget.
|
||||||
|
data NavWidgetSettings = NavWidgetSettings
|
||||||
|
{ -- | Label for the first page link. Examples: 1, First, ≪, ⋘.
|
||||||
|
nwsFirst :: Text
|
||||||
|
-- | Label for the last page link. The parameter is the number of the
|
||||||
|
-- last page. Examples: The page number, Last, ≫, ⋙.
|
||||||
|
, nwsLast :: Int -> Text
|
||||||
|
-- | Label for the previous page link. The parameter is the page number.
|
||||||
|
-- Examples: The page number, Previous, <, ≪.
|
||||||
|
, nwsPrev :: Int -> Text
|
||||||
|
-- | Label for the next page link. The parameter is the page number.
|
||||||
|
-- Examples: The page number, Next, >, ≫.
|
||||||
|
, nwsNext :: Int -> Text
|
||||||
|
-- | Label for the current page. The parameters are the current page
|
||||||
|
-- number, and the total number of pages. Example: /Page 3 of 8/.
|
||||||
|
, nwsCurrent :: Int -> Int -> Text
|
||||||
|
}
|
||||||
|
|
||||||
|
instance Default NavWidgetSettings where
|
||||||
|
def = NavWidgetSettings
|
||||||
|
{ nwsFirst = "≪"
|
||||||
|
, nwsLast = \ _ -> "≫"
|
||||||
|
, nwsPrev = \ _ -> "<"
|
||||||
|
, nwsNext = \ _ -> ">"
|
||||||
|
, nwsCurrent = F.sformat (F.int F.% " / " F.% F.int)
|
||||||
|
}
|
||||||
|
|
||||||
|
pageNavWidget
|
||||||
|
:: NavModel
|
||||||
|
-> NavWidgetSettings
|
||||||
|
-> (Int -> Route site)
|
||||||
|
-> WidgetT site IO ()
|
||||||
|
pageNavWidget nm nws route =
|
||||||
|
[whamlet|
|
||||||
|
<ul>
|
||||||
|
$if nmFirst nm
|
||||||
|
<li>
|
||||||
|
<a href=@{route 1}>#{nwsFirst nws}
|
||||||
|
<li>#{nwsCurrent nws (nmCurrent nm) (nmTotal nm)}
|
||||||
|
$if nmLast nm
|
||||||
|
<li>
|
||||||
|
<a href=@{route $ nmTotal nm}>#{nwsLast nws $ nmTotal nm}
|
||||||
|
|]
|
|
@ -46,12 +46,15 @@ library
|
||||||
Data.Git.Local
|
Data.Git.Local
|
||||||
Data.Hourglass.Local
|
Data.Hourglass.Local
|
||||||
Data.List.Local
|
Data.List.Local
|
||||||
|
Data.Paginate.Local
|
||||||
Data.Text.UTF8.Local
|
Data.Text.UTF8.Local
|
||||||
Data.Text.Lazy.UTF8.Local
|
Data.Text.Lazy.UTF8.Local
|
||||||
Data.Time.Clock.Local
|
Data.Time.Clock.Local
|
||||||
Network.SSH.Local
|
Network.SSH.Local
|
||||||
Text.FilePath.Local
|
Text.FilePath.Local
|
||||||
Text.Jasmine.Local
|
Text.Jasmine.Local
|
||||||
|
Yesod.Paginate.Local
|
||||||
|
|
||||||
Vervis.Application
|
Vervis.Application
|
||||||
Vervis.BinaryBody
|
Vervis.BinaryBody
|
||||||
Vervis.Changes
|
Vervis.Changes
|
||||||
|
@ -136,6 +139,8 @@ library
|
||||||
-- unmaintained and darcs has its own copy
|
-- unmaintained and darcs has its own copy
|
||||||
, darcs
|
, darcs
|
||||||
, data-default
|
, data-default
|
||||||
|
-- for Data.Paginate.Local
|
||||||
|
, data-default-class
|
||||||
, directory
|
, directory
|
||||||
-- for Data.Git.Local
|
-- for Data.Git.Local
|
||||||
, directory-tree
|
, directory-tree
|
||||||
|
|
Loading…
Reference in a new issue