Improve web pages

This commit is contained in:
Andrea Bedini 2022-10-27 11:56:00 +08:00
parent 37022542cc
commit 72f2efc615
6 changed files with 166 additions and 103 deletions

View File

@ -85,9 +85,11 @@ buildAction
packageVersions <- getPackageVersions inputDir packageVersions <- getPackageVersions inputDir
makeContentsPage currentTime outputDir packageVersions makeIndexPage outputDir
makeTimelinePage currentTime outputDir packageVersions makeAllPackagesPage currentTime outputDir packageVersions
makeAllPackageVersionsPage currentTime outputDir packageVersions
for_ packageVersions $ makePackageVersionPage inputDir outputDir for_ packageVersions $ makePackageVersionPage inputDir outputDir

View File

@ -4,12 +4,13 @@
{-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TemplateHaskell #-}
module Foliage.Pages module Foliage.Pages
( contentsPageTemplate, ( allPackagesPageTemplate,
timelinePageTemplate, allPackageVersionsPageTemplate,
packageVersionPageTemplate, packageVersionPageTemplate,
makeContentsPage, makeAllPackagesPage,
makePackageVersionPage, makePackageVersionPage,
makeTimelinePage, makeAllPackageVersionsPage,
makeIndexPage,
) )
where where
@ -21,7 +22,7 @@ import Data.Ord (Down (Down))
import Data.Text.Lazy.IO.Utf8 qualified as TL import Data.Text.Lazy.IO.Utf8 qualified as TL
import Data.Time (UTCTime) import Data.Time (UTCTime)
import Data.Time.Clock.POSIX (POSIXTime, utcTimeToPOSIXSeconds) import Data.Time.Clock.POSIX (POSIXTime, utcTimeToPOSIXSeconds)
import Development.Shake (Action, liftIO) import Development.Shake (Action, traced)
import Distribution.Aeson (jsonGenericPackageDescription) import Distribution.Aeson (jsonGenericPackageDescription)
import Distribution.Package (PackageIdentifier (pkgName, pkgVersion)) import Distribution.Package (PackageIdentifier (pkgName, pkgVersion))
import Distribution.Pretty (prettyShow) import Distribution.Pretty (prettyShow)
@ -36,92 +37,98 @@ import Text.Mustache (Template)
import Text.Mustache.Compile.TH (compileMustacheDir) import Text.Mustache.Compile.TH (compileMustacheDir)
import Text.Mustache.Render (renderMustache) import Text.Mustache.Render (renderMustache)
data ContentsPageEntry = ContentsPageEntry makeIndexPage :: FilePath -> Action ()
{ contentsPageEntryPkgId :: PackageIdentifier, makeIndexPage outputDir =
contentsPageEntryTimestamp :: UTCTime, traced "webpages / index" $ do
contentsPageEntryTimestampPosix :: POSIXTime, IO.createDirectoryIfMissing True outputDir
contentsPageEntrySource :: PackageVersionSource, TL.writeFile (outputDir </> "index.html") $
contentsPageEntryRevision :: Maybe RevisionSpec renderMustache indexPageTemplate $
object []
data AllPackagesPageEntry = AllPackagesPageEntry
{ allPackagesPageEntryPkgId :: PackageIdentifier,
allPackagesPageEntryTimestamp :: UTCTime,
allPackagesPageEntryTimestampPosix :: POSIXTime,
allPackagesPageEntrySource :: PackageVersionSource,
allPackagesPageEntryRevision :: Maybe RevisionSpec
} }
deriving stock (Generic) deriving stock (Generic)
deriving (ToJSON) via MyAesonEncoding ContentsPageEntry deriving (ToJSON) via MyAesonEncoding AllPackagesPageEntry
makeContentsPage :: UTCTime -> FilePath -> [PackageVersionMeta] -> Action () makeAllPackagesPage :: UTCTime -> FilePath -> [PackageVersionMeta] -> Action ()
makeContentsPage currentTime outputDir packageVersions = do makeAllPackagesPage currentTime outputDir packageVersions = do
let packages = let packages =
sortOn contentsPageEntryPkgId $ sortOn allPackagesPageEntryPkgId $
map map
( ( \PackageVersionMeta {pkgId, pkgSpec = PackageVersionSpec {packageVersionTimestamp, packageVersionRevisions, packageVersionSource}} -> ( ( \PackageVersionMeta {pkgId, pkgSpec = PackageVersionSpec {packageVersionTimestamp, packageVersionRevisions, packageVersionSource}} ->
ContentsPageEntry AllPackagesPageEntry
{ contentsPageEntryPkgId = pkgId, { allPackagesPageEntryPkgId = pkgId,
contentsPageEntryTimestamp = fromMaybe currentTime packageVersionTimestamp, allPackagesPageEntryTimestamp = fromMaybe currentTime packageVersionTimestamp,
contentsPageEntryTimestampPosix = utcTimeToPOSIXSeconds (fromMaybe currentTime packageVersionTimestamp), allPackagesPageEntryTimestampPosix = utcTimeToPOSIXSeconds (fromMaybe currentTime packageVersionTimestamp),
contentsPageEntrySource = packageVersionSource, allPackagesPageEntrySource = packageVersionSource,
contentsPageEntryRevision = listToMaybe packageVersionRevisions allPackagesPageEntryRevision = listToMaybe packageVersionRevisions
} }
) )
. head . head
. sortOn (Down . pkgVersion . pkgId) . sortOn (Down . pkgVersion . pkgId)
) )
$ groupBy ((==) `on` (pkgName . pkgId)) packageVersions $ groupBy ((==) `on` (pkgName . pkgId)) packageVersions
liftIO $ do traced "webpages / all-packages" $ do
IO.createDirectoryIfMissing True outputDir IO.createDirectoryIfMissing True (outputDir </> "all-packages")
IO.createDirectoryIfMissing True (outputDir </> "contents") TL.writeFile (outputDir </> "all-packages" </> "index.html") $
TL.writeFile (outputDir </> "contents" </> "index.html") $ renderMustache allPackagesPageTemplate $
renderMustache contentsPageTemplate $
object ["packages" .= packages] object ["packages" .= packages]
data TimelinePageEntry data AllPackageVersionsPageEntry
= TimelinePageEntryPackage = AllPackageVersionsPageEntryPackage
{ timelinePageEntryPkgId :: PackageIdentifier, { allPackageVersionsPageEntryPkgId :: PackageIdentifier,
timelinePageEntryTimestamp :: UTCTime, allPackageVersionsPageEntryTimestamp :: UTCTime,
timelinePageEntryTimestampPosix :: POSIXTime, allPackageVersionsPageEntryTimestampPosix :: POSIXTime,
timelinePageEntrySource :: PackageVersionSource allPackageVersionsPageEntrySource :: PackageVersionSource
} }
| TimelinePageEntryRevision | AllPackageVersionsPageEntryRevision
{ timelinePageEntryPkgId :: PackageIdentifier, { allPackageVersionsPageEntryPkgId :: PackageIdentifier,
timelinePageEntryTimestamp :: UTCTime, allPackageVersionsPageEntryTimestamp :: UTCTime,
timelinePageEntryTimestampPosix :: POSIXTime allPackageVersionsPageEntryTimestampPosix :: POSIXTime
} }
deriving stock (Generic) deriving stock (Generic)
deriving (ToJSON) via MyAesonEncoding TimelinePageEntry deriving (ToJSON) via MyAesonEncoding AllPackageVersionsPageEntry
makeTimelinePage :: UTCTime -> FilePath -> [PackageVersionMeta] -> Action () makeAllPackageVersionsPage :: UTCTime -> FilePath -> [PackageVersionMeta] -> Action ()
makeTimelinePage currentTime outputDir packageVersions = do makeAllPackageVersionsPage currentTime outputDir packageVersions = do
let entries = let entries =
sortOn (Down . timelinePageEntryTimestamp) $ sortOn (Down . allPackageVersionsPageEntryTimestamp) $
foldMap foldMap
( \PackageVersionMeta {pkgId, pkgSpec = PackageVersionSpec {packageVersionTimestamp, packageVersionRevisions, packageVersionSource}} -> ( \PackageVersionMeta {pkgId, pkgSpec = PackageVersionSpec {packageVersionTimestamp, packageVersionRevisions, packageVersionSource}} ->
TimelinePageEntryPackage AllPackageVersionsPageEntryPackage
{ timelinePageEntryPkgId = pkgId, { allPackageVersionsPageEntryPkgId = pkgId,
timelinePageEntryTimestamp = fromMaybe currentTime packageVersionTimestamp, allPackageVersionsPageEntryTimestamp = fromMaybe currentTime packageVersionTimestamp,
timelinePageEntryTimestampPosix = utcTimeToPOSIXSeconds (fromMaybe currentTime packageVersionTimestamp), allPackageVersionsPageEntryTimestampPosix = utcTimeToPOSIXSeconds (fromMaybe currentTime packageVersionTimestamp),
timelinePageEntrySource = packageVersionSource allPackageVersionsPageEntrySource = packageVersionSource
} : } :
map map
( \RevisionSpec {revisionTimestamp} -> ( \RevisionSpec {revisionTimestamp} ->
TimelinePageEntryRevision AllPackageVersionsPageEntryRevision
{ timelinePageEntryPkgId = pkgId, { allPackageVersionsPageEntryPkgId = pkgId,
timelinePageEntryTimestamp = revisionTimestamp, allPackageVersionsPageEntryTimestamp = revisionTimestamp,
timelinePageEntryTimestampPosix = utcTimeToPOSIXSeconds revisionTimestamp allPackageVersionsPageEntryTimestampPosix = utcTimeToPOSIXSeconds revisionTimestamp
} }
) )
packageVersionRevisions packageVersionRevisions
) )
packageVersions packageVersions
liftIO $ do traced "webpages / all-package-versions" $ do
IO.createDirectoryIfMissing True outputDir IO.createDirectoryIfMissing True (outputDir </> "all-package-versions")
IO.createDirectoryIfMissing True (outputDir </> "timeline") TL.writeFile (outputDir </> "all-package-versions" </> "index.html") $
TL.writeFile (outputDir </> "timeline" </> "index.html") $ renderMustache allPackageVersionsPageTemplate $
renderMustache timelinePageTemplate $
object ["entries" .= entries] object ["entries" .= entries]
makePackageVersionPage :: FilePath -> FilePath -> PackageVersionMeta -> Action () makePackageVersionPage :: FilePath -> FilePath -> PackageVersionMeta -> Action ()
makePackageVersionPage inputDir outputDir pkgMeta@PackageVersionMeta {pkgId, pkgSpec} = do makePackageVersionPage inputDir outputDir pkgMeta@PackageVersionMeta {pkgId, pkgSpec} = do
cabalFilePath <- maybe (originalCabalFile pkgMeta) pure (revisedCabalFile inputDir pkgMeta) cabalFilePath <- maybe (originalCabalFile pkgMeta) pure (revisedCabalFile inputDir pkgMeta)
pkgDesc <- readGenericPackageDescription' cabalFilePath pkgDesc <- readGenericPackageDescription' cabalFilePath
liftIO $ do traced ("webpages / package / " ++ prettyShow pkgId) $ do
IO.createDirectoryIfMissing True (outputDir </> "package" </> prettyShow pkgId) IO.createDirectoryIfMissing True (outputDir </> "package" </> prettyShow pkgId)
TL.writeFile (outputDir </> "package" </> prettyShow pkgId </> "index.html") $ TL.writeFile (outputDir </> "package" </> prettyShow pkgId </> "index.html") $
renderMustache packageVersionPageTemplate $ renderMustache packageVersionPageTemplate $
@ -130,11 +137,14 @@ makePackageVersionPage inputDir outputDir pkgMeta@PackageVersionMeta {pkgId, pkg
"pkgDesc" .= jsonGenericPackageDescription pkgDesc "pkgDesc" .= jsonGenericPackageDescription pkgDesc
] ]
contentsPageTemplate :: Template indexPageTemplate :: Template
contentsPageTemplate = $(compileMustacheDir "contents" "templates") indexPageTemplate = $(compileMustacheDir "index" "templates")
timelinePageTemplate :: Template allPackagesPageTemplate :: Template
timelinePageTemplate = $(compileMustacheDir "timeline" "templates") allPackagesPageTemplate = $(compileMustacheDir "allPackages" "templates")
allPackageVersionsPageTemplate :: Template
allPackageVersionsPageTemplate = $(compileMustacheDir "allPackageVersions" "templates")
packageVersionPageTemplate :: Template packageVersionPageTemplate :: Template
packageVersionPageTemplate = $(compileMustacheDir "packageVersion" "templates") packageVersionPageTemplate = $(compileMustacheDir "packageVersion" "templates")

View File

@ -14,21 +14,27 @@
--> -->
<script src="https://cdn.datatables.net/v/bs5/jq-3.6.0/dt-1.12.1/datatables.js"></script> <script src="https://cdn.datatables.net/v/bs5/jq-3.6.0/dt-1.12.1/datatables.js"></script>
<title> <title>
Index timeline All package versions
</title> </title>
</head> </head>
<body> <body>
<div class="container px-4 py-5"> <div class="container px-3 py-5">
<nav aria-label="breadcrumb"> <ul class="nav">
<ol class="breadcrumb"> <li class="nav-item">
<li class="breadcrumb-item active" aria-current="page"><a href="/timeline/">Timeline</a></li> <a class="nav-link" href="../index.html">Home</a>
</ol> </li>
</nav> <li class="nav-item">
<a class="nav-link" href="../all-packages/index.html">All packages</a>
</li>
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="#">All package versions</a>
</li>
</ul>
<h1 class="py-5"> <h1 class="py-5">
Index timeline All package versions
</h1> </h1>
<p> <p>
This page lists all package versions and revisions in the index. This page lists all package versions and revisions in the repository.
</p> </p>
<table class="table table-hover"> <table class="table table-hover">
<thead> <thead>
@ -41,28 +47,28 @@
</thead> </thead>
<tbody> <tbody>
{{#entries}} {{#entries}}
{{#TimelinePageEntryPackage}} {{#AllPackageVersionsPageEntryPackage}}
<tr> <tr>
<td class="col-sm-2"><a href="/package/{{timelinePageEntryPkgId}}">{{timelinePageEntryPkgId}}</a></td> <td class="col-sm-2"><a href="../package/{{allPackageVersionsPageEntryPkgId}}">{{allPackageVersionsPageEntryPkgId}}</a></td>
<td class="col-sm-1">Version</td> <td class="col-sm-1">Version</td>
<td class="col-sm-3" data-order="{{timelinePageEntryTimestampPosix}}">{{timelinePageEntryTimestamp}}</td> <td class="col-sm-3" data-order="{{allPackageVersionsPageEntryTimestampPosix}}">{{allPackageVersionsPageEntryTimestamp}}</td>
<td class="col-sm-6"> <td class="col-sm-6">
<dl class="row"> <dl class="row">
{{#timelinePageEntrySource}} {{#allPackageVersionsPageEntrySource}}
{{> packageVersionSource}} {{> packageVersionSource}}
{{/timelinePageEntrySource}} {{/allPackageVersionsPageEntrySource}}
</dl> </dl>
</td> </td>
</tr> </tr>
{{/TimelinePageEntryPackage}} {{/AllPackageVersionsPageEntryPackage}}
{{#TimelinePageEntryRevision}} {{#AllPackageVersionsPageEntryRevision}}
<tr> <tr>
<td>{{timelinePageEntryPkgId}}</td> <td>{{allPackageVersionsPageEntryPkgId}}</td>
<td>Revision</td> <td>Revision</td>
<td data-order="{{timelinePageEntryTimestampPosix}}">{{timelinePageEntryTimestamp}}</td> <td data-order="{{allPackageVersionsPageEntryTimestampPosix}}">{{allPackageVersionsPageEntryTimestamp}}</td>
<td></td> <td></td>
</tr> </tr>
{{/TimelinePageEntryRevision}} {{/AllPackageVersionsPageEntryRevision}}
{{/entries}} {{/entries}}
</tbody> </tbody>
</table> </table>

View File

@ -12,18 +12,24 @@
<link rel="stylesheet" href="https://cdn.datatables.net/v/bs5/dt-1.12.1/datatables.min.css" integrity="sha384-4+3RMUungd+Oh0juS2Jl3yQ7mPlVfsgr10NLSsqltLXIECi9ExY4d1cTtmf9aN8E" crossorigin="anonymous"> <link rel="stylesheet" href="https://cdn.datatables.net/v/bs5/dt-1.12.1/datatables.min.css" integrity="sha384-4+3RMUungd+Oh0juS2Jl3yQ7mPlVfsgr10NLSsqltLXIECi9ExY4d1cTtmf9aN8E" crossorigin="anonymous">
<script src="https://cdn.datatables.net/v/bs5/jq-3.6.0/dt-1.12.1/datatables.min.js" integrity="sha384-eU1uLDC5C4YCIouMauJZjbrnSmIiICWWAPdnZjRkNnuDxG+eJFN/EhW5GlKPAIVl" crossorigin="anonymous"></script> <script src="https://cdn.datatables.net/v/bs5/jq-3.6.0/dt-1.12.1/datatables.min.js" integrity="sha384-eU1uLDC5C4YCIouMauJZjbrnSmIiICWWAPdnZjRkNnuDxG+eJFN/EhW5GlKPAIVl" crossorigin="anonymous"></script>
<title> <title>
Index contents All packages
</title> </title>
</head> </head>
<body> <body>
<div class="container px-4 py-5"> <div class="container px-4 py-5">
<nav aria-label="breadcrumb"> <ul class="nav">
<ol class="breadcrumb"> <li class="nav-item">
<li class="breadcrumb-item active" aria-current="page"><a href="/contents/">Contents</a></li> <a class="nav-link" href="../index.html">Home</a>
</ol> </li>
</nav> <li class="nav-item">
<a class="nav-link active" aria-current="page" href="#">All packages</a>
</li>
<li class="nav-item">
<a class="nav-link" href="../all-package-versions/index.html">All package versions</a>
</li>
</ul>
<h1 class="py-5"> <h1 class="py-5">
Index contents All packages
</h1> </h1>
<p> <p>
This page lists the latest version and revision of all packages in the index. This page lists the latest version and revision of all packages in the index.
@ -40,22 +46,22 @@
<tbody> <tbody>
{{#packages}} {{#packages}}
<tr> <tr>
<td class="col-sm-2"><a href="/package/{{contentsPageEntryPkgId}}">{{contentsPageEntryPkgId}}</a></td> <td class="col-sm-2"><a href="../package/{{allPackagesPageEntryPkgId}}">{{allPackagesPageEntryPkgId}}</a></td>
<td class="col-sm-3" data-order="{{contentsPageEntryTimestampPosix}}">{{contentsPageEntryTimestamp}}</td> <td class="col-sm-3" data-order="{{allPackagesPageEntryTimestampPosix}}">{{allPackagesPageEntryTimestamp}}</td>
<td class="col-sm-6"> <td class="col-sm-6">
<dl class="row"> <dl class="row">
{{#contentsPageEntrySource}} {{#allPackagesPageEntrySource}}
{{> packageVersionSource}} {{> packageVersionSource}}
{{/contentsPageEntrySource}} {{/allPackagesPageEntrySource}}
</dl> </dl>
</td> </td>
<td class="col-sm-3"> <td class="col-sm-3">
{{#contentsPageEntryRevision}} {{#allPackagesPageEntryRevision}}
Last revision at {{revisionTimestamp}} Last revision at {{revisionTimestamp}}
{{/contentsPageEntryRevision}} {{/allPackagesPageEntryRevision}}
{{^contentsPageEntryRevision}} {{^allPackagesPageEntryRevision}}
No revision No revision
{{/contentsPageEntryRevision}} {{/allPackagesPageEntryRevision}}
</td> </td>
</tr> </tr>
{{/packages}} {{/packages}}

36
templates/index.mustache Normal file
View File

@ -0,0 +1,36 @@
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/5.1.3/css/bootstrap.min.css" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/5.1.3/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
<title>
Cabal package repository
</title>
</head>
<body>
<div class="container px-4 py-5">
<ul class="nav">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="#">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="all-packages/index.html">All packages</a>
</li>
<li class="nav-item">
<a class="nav-link" href="all-package-versions/index.html">All package versions</a>
</li>
</ul>
<h1 class="py-5">
Cabal package repository
</h1>
<p>
Cabal package repository built with <a href="https://github.com/andreabedini/foliage">foliage</a>.
</p>
</div>
</body>
</html>

View File

@ -17,14 +17,17 @@
<body> <body>
{{#pkgDesc}} {{#pkgDesc}}
<div class="container px-4 py-5"> <div class="container px-4 py-5">
<nav aria-label="breadcrumb"> <ul class="nav">
<ol class="breadcrumb"> <li class="nav-item">
<li class="breadcrumb-item"><a href="/timeline/">Timeline</a></li> <a class="nav-link" href="../../index.html">Home</a>
<li class="breadcrumb-item"><a href="/timeline/?q={{name}}">{{name}}</a></li> </li>
<li class="breadcrumb-item active" aria-current="page">{{version}}</li> <li class="nav-item">
</ol> <a class="nav-link" href="../../all-packages/index.html">All packages</a>
</nav> </li>
<h1 class="py-5"> <li class="nav-item">
<a class="nav-link" href="../../all-package-versions/index.html">All package versions</a>
</li>
</ul> <h1 class="py-5">
{{name}}-{{version}} {{name}}-{{version}}
</h1> </h1>
<dl class="row class="px-4 py-5"> <dl class="row class="px-4 py-5">