Allow ticket author to be a remote actor

This commit is contained in:
fr33domlover 2019-06-07 04:26:32 +00:00
parent d73b113b4f
commit b1897a20c0
26 changed files with 281 additions and 149 deletions

View file

@ -281,14 +281,13 @@ Ticket
project ProjectId project ProjectId
number Int number Int
created UTCTime created UTCTime
creator PersonId
title Text title Text
source Text -- Pandoc Markdown source Text -- Pandoc Markdown
description Text -- HTML description Text -- HTML
assignee PersonId Maybe assignee PersonId Maybe
status TicketStatus status TicketStatus
closed UTCTime closed UTCTime
closer PersonId closer PersonId Maybe
discuss DiscussionId discuss DiscussionId
followers FollowerSetId followers FollowerSetId
@ -296,6 +295,18 @@ Ticket
UniqueTicketDiscussion discuss UniqueTicketDiscussion discuss
UniqueTicketFollowers followers UniqueTicketFollowers followers
TicketAuthorLocal
ticket TicketId
author PersonId
UniqueTicketAuthorLocal ticket
TicketAuthorRemote
ticket TicketId
author RemoteActorId
UniqueTicketAuthorRemote ticket
TicketDependency TicketDependency
parent TicketId parent TicketId
child TicketId child TicketId

View file

@ -0,0 +1,11 @@
TicketAuthorLocal
ticket TicketId
author PersonId
UniqueTicketAuthorLocal ticket
TicketAuthorRemote
ticket TicketId
author RemoteActorId
UniqueTicketAuthorRemote ticket

View file

@ -0,0 +1,24 @@
TicketAuthorLocal
ticket TicketId
author Int64
UniqueTicketAuthorLocal ticket
Ticket
project Int64
number Int
created UTCTime
creator Int64
title Text
source Text -- Pandoc Markdown
description Text -- HTML
assignee Int64 Maybe
status Text
closed UTCTime
closer Int64
discuss Int64
followers Int64
UniqueTicket project number
UniqueTicketDiscussion discuss
UniqueTicketFollowers followers

View file

@ -17,11 +17,14 @@ module Data.Either.Local
( maybeRight ( maybeRight
, maybeLeft , maybeLeft
, requireEither , requireEither
, requireEitherAlt
) )
where where
import Prelude import Prelude
import Control.Applicative
maybeRight :: Either a b -> Maybe b maybeRight :: Either a b -> Maybe b
maybeRight (Left _) = Nothing maybeRight (Left _) = Nothing
maybeRight (Right b) = Just b maybeRight (Right b) = Just b
@ -35,3 +38,13 @@ requireEither Nothing Nothing = Left False
requireEither (Just _) (Just _) = Left True requireEither (Just _) (Just _) = Left True
requireEither (Just x) Nothing = Right $ Left x requireEither (Just x) Nothing = Right $ Left x
requireEither Nothing (Just y) = Right $ Right y requireEither Nothing (Just y) = Right $ Right y
requireEitherAlt
:: Applicative f
=> f (Maybe a) -> f (Maybe b) -> String -> String -> f (Either a b)
requireEitherAlt get1 get2 errNone errBoth = liftA2 mk get1 get2
where
mk Nothing Nothing = error errNone
mk (Just _) (Just _) = error errBoth
mk (Just x) Nothing = Left x
mk Nothing (Just y) = Right y

View file

@ -123,7 +123,6 @@ editTicketContentAForm ticket = Ticket
<$> pure (ticketProject ticket) <$> pure (ticketProject ticket)
<*> pure (ticketNumber ticket) <*> pure (ticketNumber ticket)
<*> pure (ticketCreated ticket) <*> pure (ticketCreated ticket)
<*> pure (ticketCreator ticket)
<*> areq textField "Title*" (Just $ ticketTitle ticket) <*> areq textField "Title*" (Just $ ticketTitle ticket)
<*> ( maybe "" (T.filter (/= '\r') . unTextarea) <$> <*> ( maybe "" (T.filter (/= '\r') . unTextarea) <$>
aopt aopt

View file

@ -52,7 +52,7 @@ import Vervis.Model.Group
import Vervis.Model.Ident (ShrIdent, shr2text) import Vervis.Model.Ident (ShrIdent, shr2text)
import Vervis.Settings (widgetFile) import Vervis.Settings (widgetFile)
import Vervis.Time (showDate) import Vervis.Time (showDate)
import Vervis.Widget.Sharer (groupLinkW, personLinkW) import Vervis.Widget.Sharer
getGroupsR :: Handler Html getGroupsR :: Handler Html
getGroupsR = do getGroupsR = do

View file

@ -78,7 +78,7 @@ import Vervis.Style
import Vervis.Time (showDate) import Vervis.Time (showDate)
import Vervis.Widget (buttonW) import Vervis.Widget (buttonW)
import Vervis.Widget.Repo import Vervis.Widget.Repo
import Vervis.Widget.Sharer (personLinkW) import Vervis.Widget.Sharer
import qualified Data.ByteString.Lazy as BL (ByteString) import qualified Data.ByteString.Lazy as BL (ByteString)
import qualified Data.Git.Local as G (createRepo) import qualified Data.Git.Local as G (createRepo)

View file

@ -96,6 +96,7 @@ import Yesod.Hashids
import qualified Web.ActivityPub as AP import qualified Web.ActivityPub as AP
import Data.Either.Local
import Data.Maybe.Local (partitionMaybePairs) import Data.Maybe.Local (partitionMaybePairs)
import Database.Persist.Local import Database.Persist.Local
import Yesod.Persist.Local import Yesod.Persist.Local
@ -117,7 +118,7 @@ import Vervis.TicketFilter (filterTickets)
import Vervis.Time (showDate) import Vervis.Time (showDate)
import Vervis.Widget (buttonW) import Vervis.Widget (buttonW)
import Vervis.Widget.Discussion (discussionW) import Vervis.Widget.Discussion (discussionW)
import Vervis.Widget.Sharer (personLinkW) import Vervis.Widget.Sharer
import Vervis.Widget.Ticket import Vervis.Widget.Ticket
getTicketsR :: ShrIdent -> PrjIdent -> Handler Html getTicketsR :: ShrIdent -> PrjIdent -> Handler Html
@ -164,18 +165,18 @@ postTicketsR shar proj = do
{ ticketProject = pid { ticketProject = pid
, ticketNumber = projectNextTicket project , ticketNumber = projectNextTicket project
, ticketCreated = now , ticketCreated = now
, ticketCreator = author
, ticketTitle = ntTitle nt , ticketTitle = ntTitle nt
, ticketSource = source , ticketSource = source
, ticketDescription = descHtml , ticketDescription = descHtml
, ticketAssignee = Nothing , ticketAssignee = Nothing
, ticketStatus = TSNew , ticketStatus = TSNew
, ticketClosed = UTCTime (ModifiedJulianDay 0) 0 , ticketClosed = UTCTime (ModifiedJulianDay 0) 0
, ticketCloser = author , ticketCloser = Nothing
, ticketDiscuss = did , ticketDiscuss = did
, ticketFollowers = fsid , ticketFollowers = fsid
} }
tid <- insert ticket tid <- insert ticket
insert_ $ TicketAuthorLocal tid author
let mktparam (fid, v) = TicketParamText let mktparam (fid, v) = TicketParamText
{ ticketParamTextTicket = tid { ticketParamTextTicket = tid
, ticketParamTextField = fid , ticketParamTextField = fid
@ -221,7 +222,7 @@ getTicketR :: ShrIdent -> PrjIdent -> Int -> Handler TypedContent
getTicketR shar proj num = do getTicketR shar proj num = do
mpid <- maybeAuthId mpid <- maybeAuthId
( wshr, wfl, ( wshr, wfl,
author, massignee, closer, ticket, tparams, eparams, deps, rdeps) <- author, massignee, mcloser, ticket, tparams, eparams, deps, rdeps) <-
runDB $ do runDB $ do
(jid, wshr, wid, wfl) <- do (jid, wshr, wid, wfl) <- do
Entity s sharer <- getBy404 $ UniqueSharer shar Entity s sharer <- getBy404 $ UniqueSharer shar
@ -238,19 +239,37 @@ getTicketR shar proj num = do
, workflowIdent w , workflowIdent w
) )
Entity tid ticket <- getBy404 $ UniqueTicket jid num Entity tid ticket <- getBy404 $ UniqueTicket jid num
author <- do author <-
person <- get404 $ ticketCreator ticket requireEitherAlt
get404 $ personIdent person (do mtal <- getValBy $ UniqueTicketAuthorLocal tid
for mtal $ \ tal -> do
p <- getJust $ ticketAuthorLocalAuthor tal
getJust $ personIdent p
)
(do mtar <- getValBy $ UniqueTicketAuthorRemote tid
for mtar $ \ tar -> do
ra <- getJust $ ticketAuthorRemoteAuthor tar
i <- getJust $ remoteActorInstance ra
return (i, ra)
)
"Ticket doesn't have author"
"Ticket has both local and remote author"
massignee <- for (ticketAssignee ticket) $ \ apid -> do massignee <- for (ticketAssignee ticket) $ \ apid -> do
person <- get404 apid person <- get404 apid
sharer <- get404 $ personIdent person sharer <- get404 $ personIdent person
return (sharer, fromMaybe False $ (== apid) <$> mpid) return (sharer, fromMaybe False $ (== apid) <$> mpid)
closer <- mcloser <-
case ticketStatus ticket of case ticketStatus ticket of
TSClosed -> do TSClosed ->
person <- get404 $ ticketCloser ticket case ticketCloser ticket of
get404 $ personIdent person Just pidCloser -> Just <$> do
_ -> return author person <- getJust pidCloser
getJust $ personIdent person
Nothing -> error "Closer not set for closed ticket"
_ ->
case ticketCloser ticket of
Just _ -> error "Closer set for open ticket"
Nothing -> return Nothing
tparams <- getTicketTextParams tid wid tparams <- getTicketTextParams tid wid
eparams <- getTicketEnumParams tid wid eparams <- getTicketEnumParams tid wid
deps <- E.select $ E.from $ \ (dep `E.InnerJoin` t) -> do deps <- E.select $ E.from $ \ (dep `E.InnerJoin` t) -> do
@ -263,7 +282,7 @@ getTicketR shar proj num = do
return t return t
return return
( wshr, wfl ( wshr, wfl
, author, massignee, closer, ticket, tparams, eparams , author, massignee, mcloser, ticket, tparams, eparams
, deps, rdeps , deps, rdeps
) )
encodeHid <- getEncodeKeyHashid encodeHid <- getEncodeKeyHashid
@ -287,6 +306,10 @@ getTicketR shar proj num = do
encodeRouteHome <- getEncodeRouteHome encodeRouteHome <- getEncodeRouteHome
let siblingUri = let siblingUri =
encodeRouteHome . TicketR shar proj . ticketNumber . entityVal encodeRouteHome . TicketR shar proj . ticketNumber . entityVal
host =
case author of
Left _ -> hLocal
Right (i, _) -> instanceHost i
ticketAP = AP.Ticket ticketAP = AP.Ticket
{ AP.ticketLocal = Just { AP.ticketLocal = Just
( hLocal ( hLocal
@ -307,7 +330,11 @@ getTicketR shar proj num = do
) )
, AP.ticketAttributedTo = , AP.ticketAttributedTo =
encodeRouteLocal $ SharerR $ sharerIdent author case author of
Left sharer ->
encodeRouteLocal $ SharerR $ sharerIdent sharer
Right (_inztance, actor) ->
remoteActorIdent actor
, AP.ticketPublished = Just $ ticketCreated ticket , AP.ticketPublished = Just $ ticketCreated ticket
, AP.ticketUpdated = Nothing , AP.ticketUpdated = Nothing
, AP.ticketName = Just $ "#" <> T.pack (show num) , AP.ticketName = Just $ "#" <> T.pack (show num)
@ -322,7 +349,7 @@ getTicketR shar proj num = do
, AP.ticketDependsOn = map siblingUri deps , AP.ticketDependsOn = map siblingUri deps
, AP.ticketDependedBy = map siblingUri rdeps , AP.ticketDependedBy = map siblingUri rdeps
} }
provideHtmlAndAP ticketAP $(widgetFile "ticket/one") provideHtmlAndAP' host ticketAP $(widgetFile "ticket/one")
putTicketR :: ShrIdent -> PrjIdent -> Int -> Handler Html putTicketR :: ShrIdent -> PrjIdent -> Int -> Handler Html
putTicketR shar proj num = do putTicketR shar proj num = do
@ -438,7 +465,7 @@ postTicketCloseR shr prj num = do
[ TicketAssignee =. Nothing [ TicketAssignee =. Nothing
, TicketStatus =. TSClosed , TicketStatus =. TSClosed
, TicketClosed =. now , TicketClosed =. now
, TicketCloser =. pid , TicketCloser =. Just pid
] ]
return True return True
setMessage $ setMessage $
@ -460,7 +487,7 @@ postTicketOpenR shr prj num = do
TSClosed -> do TSClosed -> do
update tid update tid
[ TicketStatus =. TSTodo [ TicketStatus =. TSTodo
, TicketCloser =. ticketCreator ticket , TicketCloser =. Nothing
] ]
return True return True
_ -> return False _ -> return False
@ -768,24 +795,42 @@ getTicketDeps forward shr prj num = do
Entity sid _ <- getBy404 $ UniqueSharer shr Entity sid _ <- getBy404 $ UniqueSharer shr
Entity jid _ <- getBy404 $ UniqueProject prj sid Entity jid _ <- getBy404 $ UniqueProject prj sid
Entity tid _ <- getBy404 $ UniqueTicket jid num Entity tid _ <- getBy404 $ UniqueTicket jid num
E.select $ E.from $ fmap (map toRow) $ E.select $ E.from $
\ ( td `E.InnerJoin` \ ( td
ticket `E.InnerJoin` `E.InnerJoin` t
person `E.InnerJoin` `E.LeftOuterJoin` (tal `E.InnerJoin` p `E.InnerJoin` s)
sharer `E.LeftOuterJoin` (tar `E.InnerJoin` ra `E.InnerJoin` i)
) -> do ) -> do
E.on $ person E.^. PersonIdent E.==. sharer E.^. SharerId E.on $ ra E.?. RemoteActorInstance E.==. i E.?. InstanceId
E.on $ ticket E.^. TicketCreator E.==. person E.^. PersonId E.on $ tar E.?. TicketAuthorRemoteAuthor E.==. ra E.?. RemoteActorId
E.on $ td E.^. to' E.==. ticket E.^. TicketId E.on $ E.just (t E.^. TicketId) E.==. tar E.?. TicketAuthorRemoteTicket
E.on $ p E.?. PersonIdent E.==. s E.?. SharerId
E.on $ tal E.?. TicketAuthorLocalAuthor E.==. p E.?. PersonId
E.on $ E.just (t E.^. TicketId) E.==. tal E.?. TicketAuthorLocalTicket
E.on $ td E.^. to' E.==. t E.^. TicketId
E.where_ $ td E.^. from' E.==. E.val tid E.where_ $ td E.^. from' E.==. E.val tid
E.orderBy [E.asc $ ticket E.^. TicketNumber] E.orderBy [E.asc $ t E.^. TicketNumber]
return return
( ticket E.^. TicketNumber ( t E.^. TicketNumber
, sharer , s
, ticket E.^. TicketTitle , i
, ticket E.^. TicketStatus , ra
, t E.^. TicketTitle
, t E.^. TicketStatus
) )
defaultLayout $(widgetFile "ticket/dep/list") defaultLayout $(widgetFile "ticket/dep/list")
where
toRow (E.Value number, ms, mi, mra, E.Value title, E.Value status) =
( number
, case (ms, mi, mra) of
(Just s, Nothing, Nothing) ->
Left $ entityVal s
(Nothing, Just i, Just ra) ->
Right (entityVal i, entityVal ra)
_ -> error "Ticket author DB invalid state"
, title
, status
)
getTicketDepsR :: ShrIdent -> PrjIdent -> Int -> Handler Html getTicketDepsR :: ShrIdent -> PrjIdent -> Int -> Handler Html
getTicketDepsR = getTicketDeps True getTicketDepsR = getTicketDeps True
@ -934,16 +979,6 @@ getTicketTeamR shr prj num = do
[whamlet| [whamlet|
<div><pre>#{encodePrettyToLazyText doc} <div><pre>#{encodePrettyToLazyText doc}
|] |]
where
requireEitherAlt
:: Applicative f
=> f (Maybe a) -> f (Maybe b) -> String -> String -> f (Either a b)
requireEitherAlt get1 get2 errNone errBoth = liftA2 mk get1 get2
where
mk Nothing Nothing = error errNone
mk (Just _) (Just _) = error errBoth
mk (Just x) Nothing = Left x
mk Nothing (Just y) = Right y
getTicketEventsR :: ShrIdent -> PrjIdent -> Int -> Handler TypedContent getTicketEventsR :: ShrIdent -> PrjIdent -> Int -> Handler TypedContent
getTicketEventsR shr prj num = error "TODO not implemented" getTicketEventsR shr prj num = error "TODO not implemented"

View file

@ -527,6 +527,18 @@ changes hLocal ctx =
[ Ticket201906Source =. source [ Ticket201906Source =. source
, Ticket201906Description =. content , Ticket201906Description =. content
] ]
-- 91
, addEntities model_2019_06_06
-- 92
, unchecked $ lift $ do
tickets <- selectList ([] :: [Filter Ticket20190606]) []
let mklocal (Entity tid t) =
TicketAuthorLocal20190606 tid $ ticket20190606Creator t
insertMany_ $ map mklocal tickets
-- 93
, setFieldMaybe "Ticket" "closer"
-- 94
, removeField "Ticket" "creator"
] ]
migrateDB :: MonadIO m => Text -> HashidsContext -> ReaderT SqlBackend m (Either Text (Int, Int)) migrateDB :: MonadIO m => Text -> HashidsContext -> ReaderT SqlBackend m (Either Text (Int, Int))

View file

@ -57,6 +57,10 @@ module Vervis.Migration.Model
, Message201906 , Message201906
, Ticket201906Generic (..) , Ticket201906Generic (..)
, Ticket201906 , Ticket201906
, model_2019_06_06
, Ticket20190606Generic (..)
, Ticket20190606
, TicketAuthorLocal20190606Generic (..)
) )
where where
@ -146,3 +150,9 @@ makeEntitiesMigration "201906"
makeEntitiesMigration "201906" makeEntitiesMigration "201906"
$(modelFile "migrations/2019_06_03.model") $(modelFile "migrations/2019_06_03.model")
model_2019_06_06 :: [Entity SqlBackend]
model_2019_06_06 = $(schema "2019_06_06")
makeEntitiesMigration "20190606"
$(modelFile "migrations/2019_06_06_mig.model")

View file

@ -47,34 +47,51 @@ getTicketSummaries
-> Maybe (SqlExpr (Entity Ticket) -> [SqlExpr OrderBy]) -> Maybe (SqlExpr (Entity Ticket) -> [SqlExpr OrderBy])
-> ProjectId -> ProjectId
-> AppDB [TicketSummary] -> AppDB [TicketSummary]
getTicketSummaries mfilt morder jid = do getTicketSummaries mfilt morder jid = fmap (map toSummary) $ select $ from $
let toSummary (Value n, Entity _ s, Value c, Value t, Value d, Value r) = \ ( t
TicketSummary `LeftOuterJoin` (tal `InnerJoin` p `InnerJoin` s)
{ tsNumber = n `LeftOuterJoin` (tar `InnerJoin` ra `InnerJoin` i)
, tsCreatedBy = s `InnerJoin` d
, tsCreatedAt = c `LeftOuterJoin` m
, tsTitle = t ) -> do
, tsStatus = d on $ just (d ^. DiscussionId) ==. m ?. MessageRoot
, tsComments = r on $ t ^. TicketDiscuss ==. d ^. DiscussionId
} on $ ra ?. RemoteActorInstance ==. i ?. InstanceId
fmap (map toSummary) $ select $ from $ on $ tar ?. TicketAuthorRemoteAuthor ==. ra ?. RemoteActorId
\ (t `InnerJoin` p `InnerJoin` s `InnerJoin` d `LeftOuterJoin` m) -> do on $ just (t ^. TicketId) ==. tar ?. TicketAuthorRemoteTicket
on $ just (d ^. DiscussionId) ==. m ?. MessageRoot on $ p ?. PersonIdent ==. s ?. SharerId
on $ t ^. TicketDiscuss ==. d ^. DiscussionId on $ tal ?. TicketAuthorLocalAuthor ==. p ?. PersonId
on $ p ^. PersonIdent ==. s ^. SharerId on $ just (t ^. TicketId) ==. tal ?. TicketAuthorLocalTicket
on $ t ^. TicketCreator ==. p ^. PersonId where_ $ t ^. TicketProject ==. val jid
where_ $ t ^. TicketProject ==. val jid groupBy $ t ^. TicketId
groupBy (t ^. TicketId, s ^. SharerId) for_ mfilt $ \ filt -> where_ $ filt t
for_ mfilt $ \ filt -> where_ $ filt t for_ morder $ \ order -> orderBy $ order t
for_ morder $ \ order -> orderBy $ order t return
return ( t ^. TicketNumber
( t ^. TicketNumber , s
, s , i
, t ^. TicketCreated , ra
, t ^. TicketTitle , t ^. TicketCreated
, t ^. TicketStatus , t ^. TicketTitle
, count $ m ?. MessageId , t ^. TicketStatus
) , count $ m ?. MessageId
)
where
toSummary (Value n, ms, mi, mra, Value c, Value t, Value d, Value r) =
TicketSummary
{ tsNumber = n
, tsCreatedBy =
case (ms, mi, mra) of
(Just s, Nothing, Nothing) ->
Left $ entityVal s
(Nothing, Just i, Just ra) ->
Right (entityVal i, entityVal ra)
_ -> error "Ticket author DB invalid state"
, tsCreatedAt = c
, tsTitle = t
, tsStatus = d
, tsComments = r
}
-- | Get the child-parent ticket number pairs of all the ticket dependencies -- | Get the child-parent ticket number pairs of all the ticket dependencies
-- in the given project, in ascending order by child, and then ascending order -- in the given project, in ascending order by child, and then ascending order

View file

@ -45,7 +45,7 @@ import Vervis.Model
import Vervis.Model.Ident import Vervis.Model.Ident
import Vervis.Render (renderSourceT) import Vervis.Render (renderSourceT)
import Vervis.Settings (widgetFile) import Vervis.Settings (widgetFile)
import Vervis.Widget.Sharer (personLinkW) import Vervis.Widget.Sharer
actorLinkW :: MessageTreeNodeAuthor -> Widget actorLinkW :: MessageTreeNodeAuthor -> Widget
actorLinkW actor = $(widgetFile "widget/actor-link") actorLinkW actor = $(widgetFile "widget/actor-link")

View file

@ -15,28 +15,40 @@
module Vervis.Widget.Sharer module Vervis.Widget.Sharer
( sharerLinkW ( sharerLinkW
, personLinkW , sharerLinkFedW
, groupLinkW
) )
where where
import Prelude import Prelude
import Yesod.Core (Route) import Yesod.Core
import Network.FedURI
import Vervis.Foundation import Vervis.Foundation
import Vervis.Model import Vervis.Model
import Vervis.Model.Ident (ShrIdent, shr2text) import Vervis.Model.Ident (ShrIdent, shr2text)
import Vervis.Settings (widgetFile) import Vervis.Settings (widgetFile)
link :: (ShrIdent -> Route App) -> Sharer -> Widget
link route sharer = $(widgetFile "sharer-link")
sharerLinkW :: Sharer -> Widget sharerLinkW :: Sharer -> Widget
sharerLinkW = link SharerR sharerLinkW sharer =
[whamlet|
<a href=@{SharerR $ sharerIdent sharer}>
$maybe name <- sharerName sharer
#{name}
$nothing
#{shr2text $ sharerIdent sharer}
|]
personLinkW :: Sharer -> Widget sharerLinkFedW :: Either Sharer (Instance, RemoteActor) -> Widget
personLinkW = link SharerR sharerLinkFedW (Left sharer) = sharerLinkW sharer
sharerLinkFedW (Right (inztance, actor)) =
groupLinkW :: Sharer -> Widget [whamlet|
groupLinkW = link SharerR <a href="#{renderFedURI uActor}">
$maybe name <- remoteActorName actor
#{name}
$nothing
(?)
|]
where
uActor = l2f (instanceHost inztance) (remoteActorIdent actor)

View file

@ -1,6 +1,6 @@
{- This file is part of Vervis. {- This file is part of Vervis.
- -
- Written in 2016 by fr33domlover <fr33domlover@riseup.net>. - Written in 2016, 2019 by fr33domlover <fr33domlover@riseup.net>.
- -
- Copying is an act of love. Please copy, reuse and share. - Copying is an act of love. Please copy, reuse and share.
- -
@ -45,11 +45,11 @@ import Vervis.Model.Ticket
import Vervis.Settings (widgetFile) import Vervis.Settings (widgetFile)
import Vervis.Style import Vervis.Style
import Vervis.Time (showDate) import Vervis.Time (showDate)
import Vervis.Widget.Sharer (personLinkW) import Vervis.Widget.Sharer
data TicketSummary = TicketSummary data TicketSummary = TicketSummary
{ tsNumber :: Int { tsNumber :: Int
, tsCreatedBy :: Sharer , tsCreatedBy :: Either Sharer (Instance, RemoteActor)
, tsCreatedAt :: UTCTime , tsCreatedAt :: UTCTime
, tsTitle :: Text , tsTitle :: Text
, tsStatus :: TicketStatus , tsStatus :: TicketStatus

View file

@ -18,6 +18,7 @@ module Yesod.ActivityPub
, deliverActivity , deliverActivity
, forwardActivity , forwardActivity
, provideHtmlAndAP , provideHtmlAndAP
, provideHtmlAndAP'
) )
where where
@ -121,25 +122,30 @@ provideHtmlAndAP
=> a -> WidgetFor site () -> HandlerFor site TypedContent => a -> WidgetFor site () -> HandlerFor site TypedContent
provideHtmlAndAP object widget = do provideHtmlAndAP object widget = do
host <- getsYesod siteInstanceHost host <- getsYesod siteInstanceHost
provideHtmlAndAP' host object widget
provideHtmlAndAP'
:: (YesodActivityPub site, ActivityPub a)
=> Text -> a -> WidgetFor site () -> HandlerFor site TypedContent
provideHtmlAndAP' host object widget = selectRep $ do
let doc = Doc host object let doc = Doc host object
selectRep $ do provideAP $ pure doc
provideAP $ pure doc provideRep $ do
provideRep $ do mval <- lookupGetParam "prettyjson"
mval <- lookupGetParam "prettyjson" defaultLayout $
defaultLayout $ case mval of
case mval of Just "true" ->
Just "true" -> [whamlet|
<div><pre>#{encodePrettyToLazyText doc}
|]
_ -> do
widget
mroute <- getCurrentRoute
for_ mroute $ \ route -> do
params <- reqGetParams <$> getRequest
let pj = ("prettyjson", "true")
[whamlet| [whamlet|
<div><pre>#{encodePrettyToLazyText doc} <div>
<a href=@?{(route, pj : params)}>
[See JSON]
|] |]
_ -> do
widget
mroute <- getCurrentRoute
for_ mroute $ \ route -> do
params <- reqGetParams <$> getRequest
let pj = ("prettyjson", "true")
[whamlet|
<div>
<a href=@?{(route, pj : params)}>
[See JSON]
|]

View file

@ -1,6 +1,6 @@
$# This file is part of Vervis. $# This file is part of Vervis.
$# $#
$# Written in 2016 by fr33domlover <fr33domlover@riseup.net>. $# Written in 2016, 2019 by fr33domlover <fr33domlover@riseup.net>.
$# $#
$# ♡ Copying is an act of love. Please copy, reuse and share. $# ♡ Copying is an act of love. Please copy, reuse and share.
$# $#
@ -18,4 +18,4 @@ $# <http://creativecommons.org/publicdomain/zero/1.0/>.
<ul> <ul>
$forall Entity _sid sharer <- groups $forall Entity _sid sharer <- groups
<li> <li>
^{groupLinkW sharer} ^{sharerLinkW sharer}

View file

@ -1,6 +1,6 @@
$# This file is part of Vervis. $# This file is part of Vervis.
$# $#
$# Written in 2016 by fr33domlover <fr33domlover@riseup.net>. $# Written in 2016, 2019 by fr33domlover <fr33domlover@riseup.net>.
$# $#
$# ♡ Copying is an act of love. Please copy, reuse and share. $# ♡ Copying is an act of love. Please copy, reuse and share.
$# $#
@ -24,4 +24,4 @@ $# <http://creativecommons.org/publicdomain/zero/1.0/>.
<ul> <ul>
$forall Entity _sid s <- members $forall Entity _sid s <- members
<li> <li>
^{personLinkW s} ^{sharerLinkW s}

View file

@ -1,6 +1,6 @@
$# This file is part of Vervis. $# This file is part of Vervis.
$# $#
$# Written in 2016 by fr33domlover <fr33domlover@riseup.net>. $# Written in 2016, 2019 by fr33domlover <fr33domlover@riseup.net>.
$# $#
$# ♡ Copying is an act of love. Please copy, reuse and share. $# ♡ Copying is an act of love. Please copy, reuse and share.
$# $#
@ -23,7 +23,7 @@ $# <http://creativecommons.org/publicdomain/zero/1.0/>.
<td> <td>
#{showDate time} #{showDate time}
<td> <td>
^{personLinkW sharer} ^{sharerLinkW sharer}
<td> <td>
<a href=@{TicketR shr prj num}>#{num} <a href=@{TicketR shr prj num}>#{num}
<td> <td>

View file

@ -18,7 +18,7 @@ $# <http://creativecommons.org/publicdomain/zero/1.0/>.
<th>Role <th>Role
$forall (Entity _sid sharer, Value mrl) <- devs $forall (Entity _sid sharer, Value mrl) <- devs
<tr> <tr>
<td>^{personLinkW sharer} <td>^{sharerLinkW sharer}
<td> <td>
$maybe rl <- mrl $maybe rl <- mrl
#{rl2text rl} #{rl2text rl}

View file

@ -18,7 +18,7 @@ $# <http://creativecommons.org/publicdomain/zero/1.0/>.
<th>Role <th>Role
$forall (Entity _sid sharer, Value mrl) <- devs $forall (Entity _sid sharer, Value mrl) <- devs
<tr> <tr>
<td>^{personLinkW sharer} <td>^{sharerLinkW sharer}
<td> <td>
$maybe rl <- mrl $maybe rl <- mrl
#{rl2text rl} #{rl2text rl}

View file

@ -1,6 +1,6 @@
$# This file is part of Vervis. $# This file is part of Vervis.
$# $#
$# Written in 2018 by fr33domlover <fr33domlover@riseup.net>. $# Written in 2018, 2019 by fr33domlover <fr33domlover@riseup.net>.
$# $#
$# ♡ Copying is an act of love. Please copy, reuse and share. $# ♡ Copying is an act of love. Please copy, reuse and share.
$# $#
@ -17,7 +17,7 @@ $# <http://creativecommons.org/publicdomain/zero/1.0/>.
<td>By <td>By
<td> <td>
$maybe sharer <- msharer $maybe sharer <- msharer
^{personLinkW sharer} ^{sharerLinkW sharer}
$nothing $nothing
#{patchAuthorName patch} #{patchAuthorName patch}
<tr> <tr>

View file

@ -1,19 +0,0 @@
$# 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/>.
<a href=@{route $ sharerIdent sharer}>
$maybe name <- sharerName sharer
#{name}
$nothing
#{shr2text $ sharerIdent sharer}

View file

@ -1,6 +1,6 @@
$# This file is part of Vervis. $# This file is part of Vervis.
$# $#
$# Written in 2016 by fr33domlover <fr33domlover@riseup.net>. $# Written in 2016, 2019 by fr33domlover <fr33domlover@riseup.net>.
$# $#
$# ♡ Copying is an act of love. Please copy, reuse and share. $# ♡ Copying is an act of love. Please copy, reuse and share.
$# $#
@ -22,6 +22,6 @@ $# <http://creativecommons.org/publicdomain/zero/1.0/>.
<td> <td>
#{showDate $ ticketClaimRequestCreated tcr} #{showDate $ ticketClaimRequestCreated tcr}
<td> <td>
^{personLinkW sharer} ^{sharerLinkW sharer}
<td> <td>
^{renderSourceT Markdown $ ticketClaimRequestMessage tcr} ^{renderSourceT Markdown $ ticketClaimRequestMessage tcr}

View file

@ -1,6 +1,6 @@
$# This file is part of Vervis. $# This file is part of Vervis.
$# $#
$# Written in 2016, 2018 by fr33domlover <fr33domlover@riseup.net>. $# Written in 2016, 2018, 2019 by fr33domlover <fr33domlover@riseup.net>.
$# $#
$# ♡ Copying is an act of love. Please copy, reuse and share. $# ♡ Copying is an act of love. Please copy, reuse and share.
$# $#
@ -20,12 +20,12 @@ $# <http://creativecommons.org/publicdomain/zero/1.0/>.
<th>Status <th>Status
$if forward $if forward
<th>Remove dependency <th>Remove dependency
$forall (E.Value number, Entity _ author, E.Value title, E.Value status) <- rows $forall (number, author, title, status) <- rows
<tr> <tr>
<td> <td>
<a href=@{TicketR shr prj number}>#{number} <a href=@{TicketR shr prj number}>#{number}
<td> <td>
^{personLinkW author} ^{sharerLinkFedW author}
<td> <td>
<a href=@{TicketR shr prj number}>#{title} <a href=@{TicketR shr prj number}>#{title}
<td> <td>

View file

@ -1,6 +1,6 @@
$# This file is part of Vervis. $# This file is part of Vervis.
$# $#
$# Written in 2016, 2018 by fr33domlover <fr33domlover@riseup.net>. $# Written in 2016, 2018, 2019 by fr33domlover <fr33domlover@riseup.net>.
$# $#
$# ♡ Copying is an act of love. Please copy, reuse and share. $# ♡ Copying is an act of love. Please copy, reuse and share.
$# $#
@ -41,7 +41,7 @@ $# <http://creativecommons.org/publicdomain/zero/1.0/>.
<p> <p>
Created on #{showDate $ ticketCreated ticket} by Created on #{showDate $ ticketCreated ticket} by
^{personLinkW author} ^{sharerLinkFedW author}
$if ticketStatus ticket /= TSClosed $if ticketStatus ticket /= TSClosed
<p> <p>
@ -51,7 +51,7 @@ $if ticketStatus ticket /= TSClosed
^{buttonW POST "Unclaim this ticket" (TicketUnclaimR shar proj num)} ^{buttonW POST "Unclaim this ticket" (TicketUnclaimR shar proj num)}
$else $else
Assigned to ^{personLinkW assignee}. Assigned to ^{sharerLinkW assignee}.
^{buttonW POST "Unassign this ticket" (TicketUnassignR shar proj num)} ^{buttonW POST "Unassign this ticket" (TicketUnassignR shar proj num)}
$nothing $nothing
@ -90,8 +90,9 @@ $if ticketStatus ticket /= TSClosed
^{buttonW POST "Close this ticket" (TicketCloseR shar proj num)} ^{buttonW POST "Close this ticket" (TicketCloseR shar proj num)}
$of TSClosed $of TSClosed
Closed on #{showDate $ ticketClosed ticket} by Closed on #{showDate $ ticketClosed ticket}
^{personLinkW closer}. $maybe closer <- mcloser
by ^{sharerLinkW closer}.
^{buttonW POST "Reopen this ticket" (TicketOpenR shar proj num)} ^{buttonW POST "Reopen this ticket" (TicketOpenR shar proj num)}

View file

@ -1,6 +1,6 @@
$# This file is part of Vervis. $# This file is part of Vervis.
$# $#
$# Written in 2016 by fr33domlover <fr33domlover@riseup.net>. $# Written in 2016, 2019 by fr33domlover <fr33domlover@riseup.net>.
$# $#
$# ♡ Copying is an act of love. Please copy, reuse and share. $# ♡ Copying is an act of love. Please copy, reuse and share.
$# $#
@ -30,7 +30,7 @@ $# <http://creativecommons.org/publicdomain/zero/1.0/>.
<span> <span>
#{showDate $ tsCreatedAt ts} #{showDate $ tsCreatedAt ts}
^{personLinkW $ tsCreatedBy ts} ^{sharerLinkFedW $ tsCreatedBy ts}
<a href=@{TicketR shr prj $ tsNumber ts}> <a href=@{TicketR shr prj $ tsNumber ts}>
#{tsTitle ts} #{tsTitle ts}