This commit is contained in:
Dmitry Zuikov 2024-04-19 10:45:14 +03:00
parent 4f22180ab6
commit 817fd837bf
3 changed files with 103 additions and 64 deletions

View File

@ -21,6 +21,15 @@ import Lucid.Base
import Data.Text qualified as Text import Data.Text qualified as Text
import Data.Word import Data.Word
-- import Data.Generics.Generic (genericDataType)
import GHC.Generics (Generic)
import Generic.Data -- (gdataDefault, Generically(..))
-- import Data.Data (Data)
-- import Generics.Deriving.Uniplate qualified as U
type MyRefChan = RefChanId L4Proto type MyRefChan = RefChanId L4Proto
@ -76,6 +85,9 @@ evolveDB = do
instance ToField HashRef where instance ToField HashRef where
toField x = toField $ show $ pretty x toField x = toField $ show $ pretty x
instance FromField HashRef where
fromField = fmap (fromString @HashRef) . fromField @String
instance Pretty (AsBase58 (PubKey 'Sign s)) => ToField (LWWRefKey s) where instance Pretty (AsBase58 (PubKey 'Sign s)) => ToField (LWWRefKey s) where
toField x = toField $ show $ pretty (AsBase58 x) toField x = toField $ show $ pretty (AsBase58 x)
@ -88,8 +100,8 @@ newtype TxHash = TxHash HashRef
deriving newtype (ToField) deriving newtype (ToField)
newtype RepoName = RepoName Text newtype RepoName = RepoName Text
deriving stock (Generic) deriving stock (Eq,Show,Generic)
deriving newtype (ToField,FromField,ToHtml) deriving newtype (ToField,FromField,ToHtml,IsString)
newtype RepoBrief = RepoBrief Text newtype RepoBrief = RepoBrief Text
deriving stock (Generic) deriving stock (Generic)
@ -97,7 +109,7 @@ newtype RepoBrief = RepoBrief Text
newtype RepoLww = RepoLww (LWWRefKey 'HBS2Basic) newtype RepoLww = RepoLww (LWWRefKey 'HBS2Basic)
deriving stock (Generic) deriving stock (Generic)
deriving newtype (ToField,FromField) deriving newtype (ToField,FromField,Pretty)
newtype RepoChannel = RepoChannel MyRefChan newtype RepoChannel = RepoChannel MyRefChan
@ -109,12 +121,12 @@ newtype RepoHeadRef = RepoHeadRef HashRef
newtype RepoHeadSeq = RepoHeadSeq Word64 newtype RepoHeadSeq = RepoHeadSeq Word64
deriving stock (Generic) deriving stock (Generic)
deriving newtype (ToField) deriving newtype (ToField,FromField)
newtype RepoHeadGK0 = RepoHeadGK0 (Maybe HashRef) newtype RepoHeadGK0 = RepoHeadGK0 (Maybe HashRef)
deriving stock (Generic) deriving stock (Generic)
deriving newtype (ToField) deriving newtype (ToField,FromField)
instance ToField RepoChannel where instance ToField RepoChannel where
toField (RepoChannel x) = toField $ show $ pretty (AsBase58 x) toField (RepoChannel x) = toField $ show $ pretty (AsBase58 x)
@ -185,28 +197,41 @@ getIndexEntries = do
pure [ s | ListVal [ SymbolVal "index", PRefChan s] <- conf ] pure [ s | ListVal [ SymbolVal "index", PRefChan s] <- conf ]
data NiceTS = NiceTS
data RepoListItem = data RepoListItem =
RepoListItem RepoListItem
{ rlRepoLww :: RepoLww { rlRepoLww :: RepoLww
, rlRepoSeq :: RepoHeadSeq
, rlRepoName :: RepoName , rlRepoName :: RepoName
, rlRepoBrief :: RepoBrief , rlRepoBrief :: RepoBrief
, rlRepoGK0 :: RepoHeadGK0
} }
deriving stock (Generic) deriving stock (Generic)
-- deriving instance Data RepoListItem via Generically RepoListItem
rlRepoLwwAsText :: SimpleGetter RepoListItem Text
rlRepoLwwAsText =
to \RepoListItem{..} -> do
Text.pack $ show $ pretty $ rlRepoLww
instance FromRow RepoListItem instance FromRow RepoListItem
selectRepoList :: (DashBoardPerks m, MonadReader DashBoardEnv m) => m [RepoListItem] selectRepoList :: (DashBoardPerks m, MonadReader DashBoardEnv m) => m [RepoListItem]
selectRepoList = withState do selectRepoList = fmap fixName <$> withState do
select_ @_ @RepoListItem [qc|select select_ @_ @RepoListItem [qc|select r.lww
r.lww , r.seq
, n.name , r.name
, b.brief , r.brief
from repo r join name n on r.lww = n.lww , r.gk0
join brief b on b.lww = r.lww from repolistview r
|] |]
where
fixName x@RepoListItem{..} | Text.length (coerce rlRepoName) < 3 = x { rlRepoName = fixed }
| otherwise = x
where fixed = Text.pack (show $ pretty (coerce @_ @(LWWRefKey 'HBS2Basic) rlRepoLww) ) & RepoName
createRepoListView :: DashBoardPerks m => DBPipeM m () createRepoListView :: DashBoardPerks m => DBPipeM m ()
createRepoListView = do createRepoListView = do
@ -222,7 +247,8 @@ with repolist as (
r.lww, r.lww,
0 as seq, 0 as seq,
coalesce(n.name, r.lww) as name, coalesce(n.name, r.lww) as name,
coalesce(b.brief, '') as brief coalesce(b.brief, '') as brief,
null as gk0
from repo r from repo r
left join name n on r.lww = n.lww left join name n on r.lww = n.lww
left join brief b on r.lww = b.lww left join brief b on r.lww = b.lww
@ -231,7 +257,8 @@ with repolist as (
lww, lww,
seq, seq,
name, name,
brief brief,
gk0
from repohead from repohead
), ),
ranked_repos as ( ranked_repos as (
@ -240,17 +267,20 @@ ranked_repos as (
seq, seq,
name, name,
brief, brief,
gk0,
row_number() over (partition by lww order by seq desc) as rn row_number() over (partition by lww order by seq desc) as rn
from repolist from repolist
order by seq desc
) )
select lww, seq, name, brief select lww, seq, name, brief, gk0
from ranked_repos from ranked_repos
where rn = 1; where rn = 1;
|] |]
createRepoHeadTable :: DashBoardPerks m => DBPipeM m () createRepoHeadTable :: DashBoardPerks m => DBPipeM m ()
createRepoHeadTable = do createRepoHeadTable = do
ddl [qc| ddl [qc|

View File

@ -1,8 +1,7 @@
{-# OPTIONS_GHC -fno-warn-orphans #-} {-# OPTIONS_GHC -fno-warn-orphans #-}
module HBS2.Git.Web.Html.Root where module HBS2.Git.Web.Html.Root where
import HBS2.Prelude import HBS2.Git.DashBoard.Prelude
import HBS2.Git.DashBoard.Types import HBS2.Git.DashBoard.Types
import HBS2.Git.DashBoard.State import HBS2.Git.DashBoard.State
@ -17,11 +16,13 @@ import Data.Maybe
import Data.Text qualified as Text import Data.Text qualified as Text
import Lucid.Base import Lucid.Base
import Lucid.Html5 hiding (for_) import Lucid.Html5 hiding (for_)
import Lucid.Htmx
import Text.Pandoc hiding (getPOSIXTime) import Text.Pandoc hiding (getPOSIXTime)
import Control.Monad.Identity import Control.Monad.Identity
import System.FilePath import System.FilePath
import Text.InterpolatedString.Perl6 (q) import Text.InterpolatedString.Perl6 (q)
import Data.Word
rootPath :: [String] -> [String] rootPath :: [String] -> [String]
rootPath = ("/":) rootPath = ("/":)
@ -33,8 +34,12 @@ myCss :: Monad m => HtmlT m ()
myCss = do myCss = do
link_ [rel_ "stylesheet", href_ (path ["css/custom.css"])] link_ [rel_ "stylesheet", href_ (path ["css/custom.css"])]
hyper_ :: Text -> Attribute
hyper_ = makeAttribute "_"
onClickCopy :: Text -> Attribute
onClickCopy s =
hyper_ [qc|on click writeText('{s}') into the navigator's clipboard add .clicked to me wait 2s remove .clicked from me|]
markdownToHtml :: Text -> Either PandocError String markdownToHtml :: Text -> Either PandocError String
markdownToHtml markdown = runPure $ do markdownToHtml markdown = runPure $ do
@ -54,7 +59,45 @@ renderMarkdown markdown = case markdownToHtml markdown of
instance ToHtml RepoBrief where instance ToHtml RepoBrief where
toHtml (RepoBrief txt) = toHtmlRaw (renderMarkdown' txt) toHtml (RepoBrief txt) = toHtmlRaw (renderMarkdown' txt)
toHtmlRaw (RepoBrief txt) = toHtmlRaw ("JOPA:" <> renderMarkdown' txt) toHtmlRaw (RepoBrief txt) = toHtmlRaw (renderMarkdown' txt)
data WithTime a = WithTime Integer a
instance ToHtml (WithTime RepoListItem) where
toHtmlRaw = pure mempty
toHtml (WithTime t it@RepoListItem{..}) = do
let now = t
let locked = isJust $ coerce @_ @(Maybe HashRef) rlRepoGK0
let url = path ["repo", Text.unpack $ view rlRepoLwwAsText it]
let t = fromIntegral $ coerce @_ @Word64 rlRepoSeq
let updated = "" <+> d
where
sec = now - t
d | sec > 86400 = pretty (sec `div` 86400) <+> "days ago"
| sec > 3600 = pretty (sec `div` 3600) <+> "hours ago"
| otherwise = pretty (sec `div` 60) <+> "minutes ago"
div_ [class_ "repo-list-item"] do
div_ [class_ "repo-info", style_ "flex: 1; flex-basis: 70%;"] do
h2_ [class_ "xclip", onClickCopy (view rlRepoLwwAsText it)] $ toHtml rlRepoName
p_ $ a_ [href_ url] (toHtml $ view rlRepoLwwAsText it)
toHtml rlRepoBrief
div_ [ ] do
div_ [ class_ "attr" ] do
div_ [ class_ "attrname"] (toHtml $ show updated)
when locked do
div_ [ class_ "attr" ] do
div_ [ class_ "attrval icon"] do
img_ [src_ "/icon/lock-closed.svg"]
rootPage :: Monad m => HtmlT m () -> HtmlT m () rootPage :: Monad m => HtmlT m () -> HtmlT m ()
rootPage content = do rootPage content = do
@ -78,6 +121,7 @@ rootPage content = do
dashboardRootPage :: (DashBoardPerks m, MonadReader DashBoardEnv m) => HtmlT m () dashboardRootPage :: (DashBoardPerks m, MonadReader DashBoardEnv m) => HtmlT m ()
dashboardRootPage = rootPage do dashboardRootPage = rootPage do
now <- liftIO getPOSIXTime <&> fromIntegral . round
items <- lift selectRepoList items <- lift selectRepoList
div_ [class_ "container main"] $ do div_ [class_ "container main"] $ do
@ -96,46 +140,8 @@ dashboardRootPage = rootPage do
section_ [id_ "repo-search-results"] do section_ [id_ "repo-search-results"] do
for_ items $ \RepoListItem{..} -> do for_ items $ \item@RepoListItem{..} -> do
toHtml (WithTime now item)
-- let t = coerce @_ @Word64 listEntrySeq
-- let h = coerce @_ @(LWWRefKey HBS2Basic) listEntryRef
-- let n = coerce @_ @(Maybe Text) listEntryName & fromMaybe ""
-- let b = coerce @_ @(Maybe Text) listEntryBrief & fromMaybe ""
-- let locked = listEntryGK0 & coerce @_ @(Maybe HashRef) & isJust
-- let days = "updated" <+> if d == 0 then "today" else viaShow d <+> "days ago"
-- where d = ( now - t ) `div` 86400
-- let s = if Text.length n > 2 then n else "unnamed"
-- let refpart = Text.take 8 $ Text.pack $ show $ pretty h
-- let sref = show $ pretty h
-- let ref = Text.pack sref
-- let suff = ["repo", sref]
-- let url = path (hrefBase <> suff)
div_ [class_ "repo-list-item"] do
div_ [class_ "repo-info", style_ "flex: 1; flex-basis: 70%;"] do
h2_ $ toHtml rlRepoName
-- [class_ "xclip", onClickCopy ref] $ toHtml (s <> "-" <> refpart)
-- p_ $ a_ [href_ url] (toHtml ref)
toHtml rlRepoBrief
-- renderMarkdown b
-- div_ [ ] do
-- div_ [ class_ "attr" ] do
-- div_ [ class_ "attrname"] (toHtml $ show days)
-- when locked do
-- div_ [ class_ "attr" ] do
-- div_ [ class_ "attrval icon"] do
-- img_ [src_ "/icon/lock-closed.svg"]
pure () pure ()

View File

@ -156,6 +156,9 @@ executable hbs2-git-dashboard
build-depends: build-depends:
base, hbs2-git-dashboard-assets, hbs2-peer, hbs2-git, suckless-conf base, hbs2-git-dashboard-assets, hbs2-peer, hbs2-git, suckless-conf
, binary , binary
, generic-deriving
, generic-data
, deriving-compat
, vector , vector
, optparse-applicative , optparse-applicative
, http-types , http-types