mirror of https://github.com/voidlizard/hbs2
wip
This commit is contained in:
parent
78a58039b2
commit
af847eae05
|
@ -3,6 +3,8 @@ packages: **/*.cabal
|
||||||
|
|
||||||
allow-newer: all
|
allow-newer: all
|
||||||
|
|
||||||
|
constraints: pandoc ==3.1.11
|
||||||
|
|
||||||
-- executable-static: True
|
-- executable-static: True
|
||||||
-- profiling: True
|
-- profiling: True
|
||||||
-- library-profiling: False
|
-- library-profiling: False
|
||||||
|
|
|
@ -68,7 +68,6 @@ common shared-properties
|
||||||
, streaming
|
, streaming
|
||||||
, streaming-bytestring
|
, streaming-bytestring
|
||||||
, streaming-commons
|
, streaming-commons
|
||||||
, streaming-utils
|
|
||||||
, cryptonite
|
, cryptonite
|
||||||
, directory
|
, directory
|
||||||
, exceptions
|
, exceptions
|
||||||
|
|
|
@ -192,7 +192,7 @@ runDashboardWeb wo = do
|
||||||
middleware $ staticPolicy (noDots >-> addBase f)
|
middleware $ staticPolicy (noDots >-> addBase f)
|
||||||
|
|
||||||
get "/" do
|
get "/" do
|
||||||
html =<< renderTextT (dashboardRootPage mempty)
|
html =<< lift (renderTextT dashboardRootPage)
|
||||||
|
|
||||||
|
|
||||||
runScotty :: DashBoardPerks m => DashBoardM m ()
|
runScotty :: DashBoardPerks m => DashBoardM m ()
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
{-# OPTIONS_GHC -fno-warn-orphans #-}
|
{-# OPTIONS_GHC -fno-warn-orphans #-}
|
||||||
{-# LANGUAGE UndecidableInstances #-}
|
{-# LANGUAGE UndecidableInstances #-}
|
||||||
|
{-# LANGUAGE AllowAmbiguousTypes #-}
|
||||||
{-# LANGUAGE PatternSynonyms #-}
|
{-# LANGUAGE PatternSynonyms #-}
|
||||||
{-# LANGUAGE ViewPatterns #-}
|
{-# LANGUAGE ViewPatterns #-}
|
||||||
module HBS2.Git.DashBoard.State where
|
module HBS2.Git.DashBoard.State where
|
||||||
|
@ -27,6 +28,7 @@ import Data.Config.Suckless
|
||||||
import DBPipe.SQLite hiding (insert)
|
import DBPipe.SQLite hiding (insert)
|
||||||
import DBPipe.SQLite.Generic as G
|
import DBPipe.SQLite.Generic as G
|
||||||
|
|
||||||
|
import Lucid.Base
|
||||||
import Data.Maybe
|
import Data.Maybe
|
||||||
import Data.Text qualified as Text
|
import Data.Text qualified as Text
|
||||||
import Text.InterpolatedString.Perl6 (qc)
|
import Text.InterpolatedString.Perl6 (qc)
|
||||||
|
@ -49,6 +51,15 @@ evolveDB = do
|
||||||
)
|
)
|
||||||
|]
|
|]
|
||||||
|
|
||||||
|
|
||||||
|
ddl [qc|
|
||||||
|
create table if not exists repochannel
|
||||||
|
( lww text not null
|
||||||
|
, channel text not null
|
||||||
|
, primary key (lww,channel)
|
||||||
|
)
|
||||||
|
|]
|
||||||
|
|
||||||
ddl [qc|
|
ddl [qc|
|
||||||
create table if not exists brief
|
create table if not exists brief
|
||||||
( lww text not null
|
( lww text not null
|
||||||
|
@ -81,23 +92,40 @@ instance ToField HashRef where
|
||||||
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)
|
||||||
|
|
||||||
|
instance FromField (LWWRefKey HBS2Basic) where
|
||||||
|
fromField = fmap fromString . fromField @String
|
||||||
|
|
||||||
|
|
||||||
newtype TxHash = TxHash HashRef
|
newtype TxHash = TxHash HashRef
|
||||||
|
deriving stock (Generic)
|
||||||
deriving newtype (ToField)
|
deriving newtype (ToField)
|
||||||
|
|
||||||
newtype RepoName = RepoName Text
|
newtype RepoName = RepoName Text
|
||||||
deriving newtype (ToField)
|
deriving stock (Generic)
|
||||||
|
deriving newtype (ToField,FromField,ToHtml)
|
||||||
|
|
||||||
newtype RepoBrief = RepoBrief Text
|
newtype RepoBrief = RepoBrief Text
|
||||||
deriving newtype (ToField)
|
deriving stock (Generic)
|
||||||
|
deriving newtype (ToField,FromField)
|
||||||
|
|
||||||
newtype RepoLww = RepoLww (LWWRefKey 'HBS2Basic)
|
newtype RepoLww = RepoLww (LWWRefKey 'HBS2Basic)
|
||||||
deriving newtype (ToField)
|
deriving stock (Generic)
|
||||||
|
deriving newtype (ToField,FromField)
|
||||||
|
|
||||||
|
newtype RepoChannel = RepoChannel MyRefChan
|
||||||
|
|
||||||
|
instance ToField RepoChannel where
|
||||||
|
toField (RepoChannel x) = toField $ show $ pretty (AsBase58 x)
|
||||||
|
|
||||||
data TxProcessedTable
|
data TxProcessedTable
|
||||||
data RepoTable
|
data RepoTable
|
||||||
|
data RepoChannelTable
|
||||||
data RepoNameTable
|
data RepoNameTable
|
||||||
data RepoBriefTable
|
data RepoBriefTable
|
||||||
|
|
||||||
|
instance HasTableName RepoChannelTable where
|
||||||
|
tableName = "repochannel"
|
||||||
|
|
||||||
instance HasTableName RepoTable where
|
instance HasTableName RepoTable where
|
||||||
tableName = "repo"
|
tableName = "repo"
|
||||||
|
|
||||||
|
@ -122,9 +150,15 @@ instance HasColumnName RepoName where
|
||||||
instance HasColumnName RepoBrief where
|
instance HasColumnName RepoBrief where
|
||||||
columnName = "brief"
|
columnName = "brief"
|
||||||
|
|
||||||
|
instance HasColumnName RepoChannel where
|
||||||
|
columnName = "channel"
|
||||||
|
|
||||||
instance HasPrimaryKey TxProcessedTable where
|
instance HasPrimaryKey TxProcessedTable where
|
||||||
primaryKey = [G.columnName @TxHash]
|
primaryKey = [G.columnName @TxHash]
|
||||||
|
|
||||||
|
instance HasPrimaryKey RepoChannelTable where
|
||||||
|
primaryKey = [G.columnName @RepoLww, G.columnName @RepoChannel]
|
||||||
|
|
||||||
instance HasPrimaryKey RepoTable where
|
instance HasPrimaryKey RepoTable where
|
||||||
primaryKey = [G.columnName @RepoLww]
|
primaryKey = [G.columnName @RepoLww]
|
||||||
|
|
||||||
|
@ -146,10 +180,29 @@ asRefChan = \case
|
||||||
getIndexEntries :: (DashBoardPerks m, HasConf m, MonadReader DashBoardEnv m) => m [MyRefChan]
|
getIndexEntries :: (DashBoardPerks m, HasConf m, MonadReader DashBoardEnv m) => m [MyRefChan]
|
||||||
getIndexEntries = do
|
getIndexEntries = do
|
||||||
conf <- getConf
|
conf <- getConf
|
||||||
|
|
||||||
pure [ s | ListVal [ SymbolVal "index", PRefChan s] <- conf ]
|
pure [ s | ListVal [ SymbolVal "index", PRefChan s] <- conf ]
|
||||||
|
|
||||||
|
|
||||||
|
data RepoListItem =
|
||||||
|
RepoListItem
|
||||||
|
{ rlRepoLww :: RepoLww
|
||||||
|
, rlRepoName :: RepoName
|
||||||
|
, rlRepoBrief :: RepoBrief
|
||||||
|
}
|
||||||
|
deriving stock (Generic)
|
||||||
|
|
||||||
|
instance FromRow RepoListItem
|
||||||
|
|
||||||
|
selectRepoList :: (DashBoardPerks m, MonadReader DashBoardEnv m) => m [RepoListItem]
|
||||||
|
selectRepoList = withState do
|
||||||
|
select_ @_ @RepoListItem [qc|select
|
||||||
|
r.lww
|
||||||
|
, n.name
|
||||||
|
, b.brief
|
||||||
|
from repo r join name n on r.lww = n.lww
|
||||||
|
join brief b on b.lww = r.lww
|
||||||
|
|]
|
||||||
|
|
||||||
updateIndex :: (DashBoardPerks m, HasConf m, MonadReader DashBoardEnv m) => m ()
|
updateIndex :: (DashBoardPerks m, HasConf m, MonadReader DashBoardEnv m) => m ()
|
||||||
updateIndex = do
|
updateIndex = do
|
||||||
debug "updateIndex"
|
debug "updateIndex"
|
||||||
|
@ -196,12 +249,17 @@ updateIndex = do
|
||||||
|
|
||||||
insert @RepoTable $ onConflictIgnore @RepoTable (Only (RepoLww gitIndexTxRef))
|
insert @RepoTable $ onConflictIgnore @RepoTable (Only (RepoLww gitIndexTxRef))
|
||||||
|
|
||||||
|
insert @RepoChannelTable $
|
||||||
|
onConflictIgnore @RepoChannelTable (RepoLww gitIndexTxRef, RepoChannel rc)
|
||||||
|
|
||||||
-- FIXME: on-conflict-update!
|
-- FIXME: on-conflict-update!
|
||||||
for_ nm $ \n -> do
|
for_ nm $ \n -> do
|
||||||
insert @RepoNameTable $ onConflictIgnore @RepoNameTable (RepoLww gitIndexTxRef, n)
|
insert @RepoNameTable $
|
||||||
|
onConflictIgnore @RepoNameTable (RepoLww gitIndexTxRef, n)
|
||||||
|
|
||||||
for_ bri $ \n -> do
|
for_ bri $ \n -> do
|
||||||
insert @RepoBriefTable $ onConflictIgnore @RepoBriefTable (RepoLww gitIndexTxRef, n)
|
insert @RepoBriefTable $
|
||||||
|
onConflictIgnore @RepoBriefTable (RepoLww gitIndexTxRef, n)
|
||||||
|
|
||||||
lift $ withState $ transactional do
|
lift $ withState $ transactional do
|
||||||
for_ txs $ \t -> do
|
for_ txs $ \t -> do
|
||||||
|
|
|
@ -1,12 +1,17 @@
|
||||||
module HBS2.Git.Web.Html.Root where
|
module HBS2.Git.Web.Html.Root where
|
||||||
|
|
||||||
import HBS2.Prelude
|
import HBS2.Prelude
|
||||||
|
|
||||||
|
import HBS2.Git.DashBoard.Types
|
||||||
|
import HBS2.Git.DashBoard.State
|
||||||
|
|
||||||
import HBS2.Base58
|
import HBS2.Base58
|
||||||
import HBS2.Peer.Proto.RefChan.Types
|
import HBS2.Peer.Proto.RefChan.Types
|
||||||
|
|
||||||
import Data.Config.Suckless
|
import Data.Config.Suckless
|
||||||
|
|
||||||
import Control.Monad.Trans.Maybe
|
import Control.Monad.Trans.Maybe
|
||||||
|
import Control.Monad.Reader
|
||||||
import Data.Maybe
|
import Data.Maybe
|
||||||
import Data.Text qualified as Text
|
import Data.Text qualified as Text
|
||||||
import Lucid.Base
|
import Lucid.Base
|
||||||
|
@ -43,11 +48,10 @@ rootPage content = do
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
dashboardRootPage :: Monad m => [Syntax c] -> HtmlT m ()
|
dashboardRootPage :: (DashBoardPerks m, MonadReader DashBoardEnv m) => HtmlT m ()
|
||||||
dashboardRootPage syn = rootPage do
|
dashboardRootPage = rootPage do
|
||||||
|
|
||||||
let channels = mempty
|
items <- lift selectRepoList
|
||||||
-- [ mchan | ListVal (SymbolVal "channel" : mchan) <- bro ]
|
|
||||||
|
|
||||||
div_ [class_ "container main"] $ do
|
div_ [class_ "container main"] $ do
|
||||||
nav_ [class_ "left"] $ do
|
nav_ [class_ "left"] $ do
|
||||||
|
@ -55,35 +59,87 @@ dashboardRootPage syn = rootPage do
|
||||||
div_ [class_ "info-block"] "Всякая разная рандомная информация хрен знает, что тут пока выводить"
|
div_ [class_ "info-block"] "Всякая разная рандомная информация хрен знает, что тут пока выводить"
|
||||||
|
|
||||||
main_ do
|
main_ do
|
||||||
for_ channels $ \chan -> void $ runMaybeT do
|
|
||||||
|
|
||||||
let title = headDef "unknown" [ t
|
section_ do
|
||||||
| ListVal [ SymbolVal "title", LitStrVal t ] <- chan
|
h1_ "Git repositories"
|
||||||
]
|
form_ [class_ "search"] do
|
||||||
let desc = mconcat [ d
|
input_ [type_ "search", id_ "search"]
|
||||||
| ListVal (SymbolVal "description" : d) <- chan
|
button_ [class_ "search"] mempty
|
||||||
] & take 5
|
|
||||||
|
|
||||||
rchan <- headMay ( catMaybes
|
|
||||||
[ fromStringMay @(RefChanId L4Proto) (Text.unpack rc)
|
|
||||||
| ListVal [SymbolVal "refchan", LitStrVal rc] <- chan
|
|
||||||
] ) & toMPlus
|
|
||||||
|
|
||||||
|
|
||||||
let alias = headMay [ x
|
section_ [id_ "repo-search-results"] do
|
||||||
| ListVal [SymbolVal "alias", LitStrVal x] <- chan
|
|
||||||
]
|
|
||||||
|
|
||||||
let url = case alias of
|
for_ items $ \RepoListItem{..} -> do
|
||||||
Just x -> Text.unpack x
|
|
||||||
Nothing -> (show . pretty . AsBase58) rchan
|
|
||||||
|
|
||||||
lift do
|
-- let t = coerce @_ @Word64 listEntrySeq
|
||||||
div_ [class_ "channel-list-item"] do
|
-- let h = coerce @_ @(LWWRefKey HBS2Basic) listEntryRef
|
||||||
h2_ $ toHtml title
|
-- let n = coerce @_ @(Maybe Text) listEntryName & fromMaybe ""
|
||||||
|
-- let b = coerce @_ @(Maybe Text) listEntryBrief & fromMaybe ""
|
||||||
|
-- let locked = listEntryGK0 & coerce @_ @(Maybe HashRef) & isJust
|
||||||
|
|
||||||
p_ $ a_ [href_ (path [url])] (toHtml (show $ pretty $ AsBase58 rchan))
|
-- let days = "updated" <+> if d == 0 then "today" else viaShow d <+> "days ago"
|
||||||
|
-- where d = ( now - t ) `div` 86400
|
||||||
|
|
||||||
for_ [ s | LitStrVal s <- desc ] $ \s -> do
|
-- let s = if Text.length n > 2 then n else "unnamed"
|
||||||
p_ (toHtml s)
|
-- 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)
|
||||||
|
|
||||||
|
-- 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 ()
|
||||||
|
-- for_ channels $ \chan -> void $ runMaybeT do
|
||||||
|
|
||||||
|
-- let title = headDef "unknown" [ t
|
||||||
|
-- | ListVal [ SymbolVal "title", LitStrVal t ] <- chan
|
||||||
|
-- ]
|
||||||
|
-- let desc = mconcat [ d
|
||||||
|
-- | ListVal (SymbolVal "description" : d) <- chan
|
||||||
|
-- ] & take 5
|
||||||
|
|
||||||
|
-- rchan <- headMay ( catMaybes
|
||||||
|
-- [ fromStringMay @(RefChanId L4Proto) (Text.unpack rc)
|
||||||
|
-- | ListVal [SymbolVal "refchan", LitStrVal rc] <- chan
|
||||||
|
-- ] ) & toMPlus
|
||||||
|
|
||||||
|
|
||||||
|
-- let alias = headMay [ x
|
||||||
|
-- | ListVal [SymbolVal "alias", LitStrVal x] <- chan
|
||||||
|
-- ]
|
||||||
|
|
||||||
|
-- let url = case alias of
|
||||||
|
-- Just x -> Text.unpack x
|
||||||
|
-- Nothing -> (show . pretty . AsBase58) rchan
|
||||||
|
|
||||||
|
-- lift do
|
||||||
|
-- div_ [class_ "channel-list-item"] do
|
||||||
|
-- h2_ $ toHtml title
|
||||||
|
|
||||||
|
-- p_ $ a_ [href_ (path [url])] (toHtml (show $ pretty $ AsBase58 rchan))
|
||||||
|
|
||||||
|
-- for_ [ s | LitStrVal s <- desc ] $ \s -> do
|
||||||
|
-- p_ (toHtml s)
|
||||||
|
|
||||||
|
|
|
@ -162,6 +162,7 @@ executable hbs2-git-dashboard
|
||||||
, wai-middleware-static-embedded
|
, wai-middleware-static-embedded
|
||||||
, lucid
|
, lucid
|
||||||
, lucid-htmx
|
, lucid-htmx
|
||||||
|
, pandoc
|
||||||
, scotty >= 0.22
|
, scotty >= 0.22
|
||||||
|
|
||||||
hs-source-dirs:
|
hs-source-dirs:
|
||||||
|
|
Loading…
Reference in New Issue