UI, Web: Re-enable ticket/MR replies view and commenting forms/buttons
This commit is contained in:
parent
d5e913d97a
commit
b99d864429
9 changed files with 340 additions and 369 deletions
|
@ -16,6 +16,7 @@
|
||||||
module Vervis.Client
|
module Vervis.Client
|
||||||
( makeServerInput
|
( makeServerInput
|
||||||
|
|
||||||
|
, comment
|
||||||
--, createThread
|
--, createThread
|
||||||
--, createReply
|
--, createReply
|
||||||
--, follow
|
--, follow
|
||||||
|
@ -112,19 +113,42 @@ makeServerInput maybeCapURI maybeSummary audience specific = do
|
||||||
}
|
}
|
||||||
return (recipientSet, remoteActors, fwdHosts, action)
|
return (recipientSet, remoteActors, fwdHosts, action)
|
||||||
|
|
||||||
|
comment
|
||||||
|
:: KeyHashid Person
|
||||||
|
-> PandocMarkdown
|
||||||
|
-> [LocalActorBy KeyHashid]
|
||||||
|
-> [LocalStageBy KeyHashid]
|
||||||
|
-> Route App
|
||||||
|
-> Maybe FedURI
|
||||||
|
-> ExceptT Text Handler (Maybe HTML, [Aud URIMode], AP.Note URIMode)
|
||||||
|
comment senderHash source actors stages topicR muParent = do
|
||||||
|
encodeRouteLocal <- getEncodeRouteLocal
|
||||||
|
encodeRouteHome <- getEncodeRouteHome
|
||||||
|
content <- ExceptT . pure $ renderPandocMarkdown source
|
||||||
|
let audience = [AudLocal actors stages]
|
||||||
|
uTopic = encodeRouteHome topicR
|
||||||
|
note = AP.Note
|
||||||
|
{ AP.noteId = Nothing
|
||||||
|
, AP.noteAttrib = encodeRouteLocal $ PersonR senderHash
|
||||||
|
, AP.noteAudience = emptyAudience
|
||||||
|
, AP.noteReplyTo = Just $ fromMaybe uTopic muParent
|
||||||
|
, AP.noteContext = Just uTopic
|
||||||
|
, AP.notePublished = Nothing
|
||||||
|
, AP.noteSource = source
|
||||||
|
, AP.noteContent = content
|
||||||
|
}
|
||||||
|
return (Nothing, audience, note)
|
||||||
|
|
||||||
{-
|
{-
|
||||||
createThread
|
createThread
|
||||||
:: (MonadSite m, SiteEnv m ~ App)
|
:: KeyHashid Person
|
||||||
=> ShrIdent
|
-> PandocMarkdown
|
||||||
-> TextPandocMarkdown
|
|
||||||
-> Host
|
-> Host
|
||||||
-> [Route App]
|
-> [Route App]
|
||||||
-> [Route App]
|
-> [Route App]
|
||||||
-> Route App
|
-> Route App
|
||||||
-> m (Either Text (Note URIMode))
|
-> ExceptT Text Handler (Maybe HTML, [Aud URIMode], AP.Note URIMode)
|
||||||
createThread shrAuthor (TextPandocMarkdown msg) hDest recipsA recipsC context = runExceptT $ do
|
createThread senderHash source hDest recipsA recipsC context = runExceptT $ do
|
||||||
error "Temporarily disabled"
|
|
||||||
{-
|
|
||||||
encodeRouteLocal <- getEncodeRouteLocal
|
encodeRouteLocal <- getEncodeRouteLocal
|
||||||
let encodeRecipRoute = ObjURI hDest . encodeRouteLocal
|
let encodeRecipRoute = ObjURI hDest . encodeRouteLocal
|
||||||
contentHtml <- ExceptT . pure $ renderPandocMarkdown msg
|
contentHtml <- ExceptT . pure $ renderPandocMarkdown msg
|
||||||
|
@ -147,7 +171,6 @@ createThread shrAuthor (TextPandocMarkdown msg) hDest recipsA recipsC context =
|
||||||
, noteSource = msg
|
, noteSource = msg
|
||||||
, noteContent = contentHtml
|
, noteContent = contentHtml
|
||||||
}
|
}
|
||||||
-}
|
|
||||||
|
|
||||||
createReply
|
createReply
|
||||||
:: ShrIdent
|
:: ShrIdent
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{- This file is part of Vervis.
|
{- This file is part of Vervis.
|
||||||
-
|
-
|
||||||
- Written in 2016, 2019 by fr33domlover <fr33domlover@riseup.net>.
|
- Written in 2016, 2019, 2022 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.
|
||||||
-
|
-
|
||||||
|
@ -14,8 +14,7 @@
|
||||||
-}
|
-}
|
||||||
|
|
||||||
module Vervis.Form.Discussion
|
module Vervis.Form.Discussion
|
||||||
( NewMessage (..)
|
( newMessageForm
|
||||||
, newMessageForm
|
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
|
|
||||||
|
@ -24,16 +23,15 @@ import Yesod.Form
|
||||||
|
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
|
|
||||||
|
import Web.Text
|
||||||
|
|
||||||
import Vervis.Foundation (Form, Handler)
|
import Vervis.Foundation (Form, Handler)
|
||||||
import Vervis.Model
|
import Vervis.Model
|
||||||
|
|
||||||
data NewMessage = NewMessage
|
newMessageAForm :: AForm Handler PandocMarkdown
|
||||||
{ nmContent :: Text
|
newMessageAForm =
|
||||||
}
|
pandocMarkdownFromText . T.filter (/= '\r') . unTextarea <$>
|
||||||
|
areq textareaField "" Nothing
|
||||||
|
|
||||||
newMessageAForm :: AForm Handler NewMessage
|
newMessageForm :: Form PandocMarkdown
|
||||||
newMessageAForm = NewMessage
|
|
||||||
<$> (T.filter (/= '\r') . unTextarea <$> areq textareaField "" Nothing)
|
|
||||||
|
|
||||||
newMessageForm :: Form NewMessage
|
|
||||||
newMessageForm = renderDivs newMessageAForm
|
newMessageForm = renderDivs newMessageAForm
|
||||||
|
|
|
@ -838,8 +838,6 @@ instance YesodBreadcrumbs App where
|
||||||
PersonFollowR _ -> ("", Nothing)
|
PersonFollowR _ -> ("", Nothing)
|
||||||
PersonUnfollowR _ -> ("", Nothing)
|
PersonUnfollowR _ -> ("", Nothing)
|
||||||
|
|
||||||
ReplyR _ -> ("", Nothing)
|
|
||||||
|
|
||||||
PersonStampR p k -> ("Stamp #" <> keyHashidText k, Just $ PersonR p)
|
PersonStampR p k -> ("Stamp #" <> keyHashidText k, Just $ PersonR p)
|
||||||
|
|
||||||
GroupR g -> ("Team &" <> keyHashidText g, Just HomeR)
|
GroupR g -> ("Team &" <> keyHashidText g, Just HomeR)
|
||||||
|
@ -910,9 +908,10 @@ instance YesodBreadcrumbs App where
|
||||||
TicketDepsR d t -> ("Dependencies", Just $ TicketR d t)
|
TicketDepsR d t -> ("Dependencies", Just $ TicketR d t)
|
||||||
TicketReverseDepsR d t -> ("Dependants", Just $ TicketR d t)
|
TicketReverseDepsR d t -> ("Dependants", Just $ TicketR d t)
|
||||||
|
|
||||||
TicketFollowR _ _ -> ("", Nothing)
|
TicketFollowR _ _ -> ("", Nothing)
|
||||||
TicketUnfollowR _ _ -> ("", Nothing)
|
TicketUnfollowR _ _ -> ("", Nothing)
|
||||||
TicketReplyR _ _ -> ("", Nothing)
|
TicketReplyR d t -> ("Reply", Just $ TicketR d t)
|
||||||
|
TicketReplyOnR d t _ -> ("Reply", Just $ TicketR d t)
|
||||||
|
|
||||||
TicketDepR d t p -> (keyHashidText p, Just $ TicketDepsR d t)
|
TicketDepR d t p -> (keyHashidText p, Just $ TicketDepsR d t)
|
||||||
|
|
||||||
|
@ -941,9 +940,10 @@ instance YesodBreadcrumbs App where
|
||||||
BundleR l c b -> ("Bundle " <> keyHashidText b, Just $ ClothR l c)
|
BundleR l c b -> ("Bundle " <> keyHashidText b, Just $ ClothR l c)
|
||||||
PatchR l c b p -> ("Patch " <> keyHashidText p, Just $ BundleR l c b)
|
PatchR l c b p -> ("Patch " <> keyHashidText p, Just $ BundleR l c b)
|
||||||
|
|
||||||
ClothApplyR _ _ -> ("", Nothing)
|
ClothApplyR _ _ -> ("", Nothing)
|
||||||
ClothFollowR _ _ -> ("", Nothing)
|
ClothFollowR _ _ -> ("", Nothing)
|
||||||
ClothUnfollowR _ _ -> ("", Nothing)
|
ClothUnfollowR _ _ -> ("", Nothing)
|
||||||
ClothReplyR _ _ -> ("", Nothing)
|
ClothReplyR l c -> ("Reply", Just $ ClothR l c)
|
||||||
|
ClothReplyOnR l c _ -> ("Reply", Just $ ClothR l c)
|
||||||
|
|
||||||
ClothDepR l c p -> (keyHashidText p, Just $ ClothDepsR l c)
|
ClothDepR l c p -> (keyHashidText p, Just $ ClothDepsR l c)
|
||||||
|
|
|
@ -29,7 +29,11 @@ module Vervis.Handler.Cloth
|
||||||
, postClothApplyR
|
, postClothApplyR
|
||||||
, postClothFollowR
|
, postClothFollowR
|
||||||
, postClothUnfollowR
|
, postClothUnfollowR
|
||||||
|
|
||||||
|
, getClothReplyR
|
||||||
, postClothReplyR
|
, postClothReplyR
|
||||||
|
, getClothReplyOnR
|
||||||
|
, postClothReplyOnR
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -120,6 +124,7 @@ import Vervis.Style
|
||||||
import Vervis.Ticket
|
import Vervis.Ticket
|
||||||
import Vervis.Time (showDate)
|
import Vervis.Time (showDate)
|
||||||
import Vervis.Web.Actor
|
import Vervis.Web.Actor
|
||||||
|
import Vervis.Web.Discussion
|
||||||
import Vervis.Web.Repo
|
import Vervis.Web.Repo
|
||||||
import Vervis.Widget
|
import Vervis.Widget
|
||||||
import Vervis.Widget.Discussion
|
import Vervis.Widget.Discussion
|
||||||
|
@ -127,6 +132,10 @@ import Vervis.Widget.Person
|
||||||
|
|
||||||
import qualified Vervis.Client as C
|
import qualified Vervis.Client as C
|
||||||
|
|
||||||
|
selectDiscussionID loomHash clothHash = do
|
||||||
|
(_, _, Entity _ ticket, _, _, _) <- getCloth404 loomHash clothHash
|
||||||
|
return $ ticketDiscuss ticket
|
||||||
|
|
||||||
getClothR :: KeyHashid Loom -> KeyHashid TicketLoom -> Handler TypedContent
|
getClothR :: KeyHashid Loom -> KeyHashid TicketLoom -> Handler TypedContent
|
||||||
getClothR loomHash clothHash = do
|
getClothR loomHash clothHash = do
|
||||||
(repoID, mbranch, ticket, author, resolve, proposal) <- runDB $ do
|
(repoID, mbranch, ticket, author, resolve, proposal) <- runDB $ do
|
||||||
|
@ -329,7 +338,7 @@ getClothR loomHash clothHash = do
|
||||||
discussionW
|
discussionW
|
||||||
(return $ ticketDiscuss ticket)
|
(return $ ticketDiscuss ticket)
|
||||||
(ClothReplyR loomHash clothHash)
|
(ClothReplyR loomHash clothHash)
|
||||||
(ReplyR . hashMessageKey)
|
(ClothReplyOnR loomHash clothHash . hashMessageKey)
|
||||||
cRelevant <- newIdent
|
cRelevant <- newIdent
|
||||||
cIrrelevant <- newIdent
|
cIrrelevant <- newIdent
|
||||||
let relevant filt =
|
let relevant filt =
|
||||||
|
@ -377,15 +386,13 @@ getClothR loomHash clothHash = do
|
||||||
|
|
||||||
getClothDiscussionR
|
getClothDiscussionR
|
||||||
:: KeyHashid Loom -> KeyHashid TicketLoom -> Handler TypedContent
|
:: KeyHashid Loom -> KeyHashid TicketLoom -> Handler TypedContent
|
||||||
getClothDiscussionR _ _ = do
|
getClothDiscussionR loomHash clothHash = do
|
||||||
error "Temporarily disabled"
|
hashMsg <- getEncodeKeyHashid
|
||||||
{-
|
serveDiscussion
|
||||||
encodeHid <- getEncodeKeyHashid
|
(ClothDiscussionR loomHash clothHash)
|
||||||
getDiscussion
|
(ClothReplyOnR loomHash clothHash . hashMsg)
|
||||||
(ProjectClothReplyR shar proj ltkhid . encodeHid)
|
(ClothReplyR loomHash clothHash)
|
||||||
(ProjectClothTopReplyR shar proj ltkhid)
|
(selectDiscussionID loomHash clothHash)
|
||||||
(selectDiscussionId shar proj ltkhid)
|
|
||||||
-}
|
|
||||||
|
|
||||||
getClothEventsR
|
getClothEventsR
|
||||||
:: KeyHashid Loom -> KeyHashid TicketLoom -> Handler TypedContent
|
:: KeyHashid Loom -> KeyHashid TicketLoom -> Handler TypedContent
|
||||||
|
@ -671,22 +678,49 @@ postClothFollowR _ = error "Temporarily disabled"
|
||||||
postClothUnfollowR :: KeyHashid Loom -> KeyHashid TicketLoom -> Handler ()
|
postClothUnfollowR :: KeyHashid Loom -> KeyHashid TicketLoom -> Handler ()
|
||||||
postClothUnfollowR _ = error "Temporarily disabled"
|
postClothUnfollowR _ = error "Temporarily disabled"
|
||||||
|
|
||||||
|
getClothReplyR :: KeyHashid Loom -> KeyHashid TicketLoom -> Handler Html
|
||||||
|
getClothReplyR loomHash clothHash =
|
||||||
|
getTopReply $ ClothReplyR loomHash clothHash
|
||||||
|
|
||||||
postClothReplyR :: KeyHashid Loom -> KeyHashid TicketLoom -> Handler Html
|
postClothReplyR :: KeyHashid Loom -> KeyHashid TicketLoom -> Handler Html
|
||||||
postClothReplyR _ _ = error "Temporarily disabled"
|
postClothReplyR loomHash clothHash =
|
||||||
{-
|
postReply
|
||||||
hLocal <- getsYesod $ appInstanceHost . appSettings
|
(ClothReplyR loomHash clothHash)
|
||||||
postTopReply
|
[LocalActorLoom loomHash]
|
||||||
hLocal
|
[ LocalStageLoomFollowers loomHash
|
||||||
[ProjectR shr prj]
|
, LocalStageClothFollowers loomHash clothHash
|
||||||
[ ProjectFollowersR shr prj
|
|
||||||
, ProjectTicketParticipantsR shr prj ltkhid
|
|
||||||
, ProjectTicketTeamR shr prj ltkhid
|
|
||||||
]
|
]
|
||||||
(ProjectTicketR shr prj ltkhid)
|
(ClothR loomHash clothHash)
|
||||||
(ProjectR shr prj)
|
Nothing
|
||||||
(ProjectTicketDiscussionR shr prj ltkhid)
|
|
||||||
(const $ ProjectTicketR shr prj ltkhid)
|
getClothReplyOnR
|
||||||
-}
|
:: KeyHashid Loom
|
||||||
|
-> KeyHashid TicketLoom
|
||||||
|
-> KeyHashid Message
|
||||||
|
-> Handler Html
|
||||||
|
getClothReplyOnR loomHash clothHash msgHash = do
|
||||||
|
msgID <- decodeKeyHashid404 msgHash
|
||||||
|
hashMsg <- getEncodeKeyHashid
|
||||||
|
getReply
|
||||||
|
(ClothReplyOnR loomHash clothHash . hashMsg)
|
||||||
|
(selectDiscussionID loomHash clothHash)
|
||||||
|
msgID
|
||||||
|
|
||||||
|
postClothReplyOnR
|
||||||
|
:: KeyHashid Loom
|
||||||
|
-> KeyHashid TicketLoom
|
||||||
|
-> KeyHashid Message
|
||||||
|
-> Handler Html
|
||||||
|
postClothReplyOnR loomHash clothHash msgHash = do
|
||||||
|
msgID <- decodeKeyHashid404 msgHash
|
||||||
|
postReply
|
||||||
|
(ClothReplyOnR loomHash clothHash msgHash)
|
||||||
|
[LocalActorLoom loomHash]
|
||||||
|
[ LocalStageLoomFollowers loomHash
|
||||||
|
, LocalStageClothFollowers loomHash clothHash
|
||||||
|
]
|
||||||
|
(ClothR loomHash clothHash)
|
||||||
|
(Just (selectDiscussionID loomHash clothHash, msgID))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -853,13 +887,6 @@ getSharerProposalR shr talkhid = do
|
||||||
where
|
where
|
||||||
here = SharerProposalR shr talkhid
|
here = SharerProposalR shr talkhid
|
||||||
|
|
||||||
getSharerProposalDiscussionR
|
|
||||||
:: ShrIdent -> KeyHashid TicketAuthorLocal -> Handler TypedContent
|
|
||||||
getSharerProposalDiscussionR shr talkhid =
|
|
||||||
getRepliesCollection (SharerProposalDiscussionR shr talkhid) $ do
|
|
||||||
(_, Entity _ lt, _, _, _, _) <- getSharerProposal404 shr talkhid
|
|
||||||
return $ localTicketDiscuss lt
|
|
||||||
|
|
||||||
getSharerProposalDepsR
|
getSharerProposalDepsR
|
||||||
:: ShrIdent -> KeyHashid TicketAuthorLocal -> Handler TypedContent
|
:: ShrIdent -> KeyHashid TicketAuthorLocal -> Handler TypedContent
|
||||||
getSharerProposalDepsR shr talkhid =
|
getSharerProposalDepsR shr talkhid =
|
||||||
|
@ -1196,13 +1223,6 @@ getRepoProposalR shr rp ltkhid = do
|
||||||
where
|
where
|
||||||
here = RepoProposalR shr rp ltkhid
|
here = RepoProposalR shr rp ltkhid
|
||||||
|
|
||||||
getRepoProposalDiscussionR
|
|
||||||
:: ShrIdent -> RpIdent -> KeyHashid LocalTicket -> Handler TypedContent
|
|
||||||
getRepoProposalDiscussionR shr rp ltkhid =
|
|
||||||
getRepliesCollection (RepoProposalDiscussionR shr rp ltkhid) $ do
|
|
||||||
(_, _, _, Entity _ lt, _, _, _, _, _) <- getRepoProposal404 shr rp ltkhid
|
|
||||||
return $ localTicketDiscuss lt
|
|
||||||
|
|
||||||
getRepoProposalDepsR
|
getRepoProposalDepsR
|
||||||
:: ShrIdent -> RpIdent -> KeyHashid LocalTicket -> Handler TypedContent
|
:: ShrIdent -> RpIdent -> KeyHashid LocalTicket -> Handler TypedContent
|
||||||
getRepoProposalDepsR shr rp ltkhid =
|
getRepoProposalDepsR shr rp ltkhid =
|
||||||
|
|
|
@ -28,8 +28,6 @@ module Vervis.Handler.Person
|
||||||
, postPersonFollowR
|
, postPersonFollowR
|
||||||
, postPersonUnfollowR
|
, postPersonUnfollowR
|
||||||
|
|
||||||
, postReplyR
|
|
||||||
|
|
||||||
, getPersonStampR
|
, getPersonStampR
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
|
@ -402,8 +400,5 @@ postPersonFollowR _ = error "Temporarily disabled"
|
||||||
postPersonUnfollowR :: KeyHashid Person -> Handler ()
|
postPersonUnfollowR :: KeyHashid Person -> Handler ()
|
||||||
postPersonUnfollowR _ = error "Temporarily disabled"
|
postPersonUnfollowR _ = error "Temporarily disabled"
|
||||||
|
|
||||||
postReplyR :: KeyHashid Message -> Handler ()
|
|
||||||
postReplyR _ = error "Temporarily disabled"
|
|
||||||
|
|
||||||
getPersonStampR :: KeyHashid Person -> KeyHashid SigKey -> Handler TypedContent
|
getPersonStampR :: KeyHashid Person -> KeyHashid SigKey -> Handler TypedContent
|
||||||
getPersonStampR = servePerActorKey personActor LocalActorPerson
|
getPersonStampR = servePerActorKey personActor LocalActorPerson
|
||||||
|
|
|
@ -26,7 +26,11 @@ module Vervis.Handler.Ticket
|
||||||
|
|
||||||
, postTicketFollowR
|
, postTicketFollowR
|
||||||
, postTicketUnfollowR
|
, postTicketUnfollowR
|
||||||
|
|
||||||
|
, getTicketReplyR
|
||||||
, postTicketReplyR
|
, postTicketReplyR
|
||||||
|
, getTicketReplyOnR
|
||||||
|
, postTicketReplyOnR
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -53,11 +57,6 @@ module Vervis.Handler.Ticket
|
||||||
, getClaimRequestsTicketR
|
, getClaimRequestsTicketR
|
||||||
, postClaimRequestsTicketR
|
, postClaimRequestsTicketR
|
||||||
, getClaimRequestNewR
|
, getClaimRequestNewR
|
||||||
, postProjectTicketDiscussionR
|
|
||||||
, getMessageR
|
|
||||||
, postProjectTicketMessageR
|
|
||||||
, getProjectTicketTopReplyR
|
|
||||||
, getProjectTicketReplyR
|
|
||||||
, postProjectTicketDepsR
|
, postProjectTicketDepsR
|
||||||
, getProjectTicketDepNewR
|
, getProjectTicketDepNewR
|
||||||
, postTicketDepOldR
|
, postTicketDepOldR
|
||||||
|
@ -67,7 +66,6 @@ module Vervis.Handler.Ticket
|
||||||
|
|
||||||
, getSharerTicketsR
|
, getSharerTicketsR
|
||||||
, getSharerTicketR
|
, getSharerTicketR
|
||||||
, getSharerTicketDiscussionR
|
|
||||||
, getSharerTicketDepsR
|
, getSharerTicketDepsR
|
||||||
, getSharerTicketReverseDepsR
|
, getSharerTicketReverseDepsR
|
||||||
, getSharerTicketTeamR
|
, getSharerTicketTeamR
|
||||||
|
@ -160,6 +158,10 @@ import Vervis.Web.Discussion
|
||||||
import Vervis.Widget.Discussion
|
import Vervis.Widget.Discussion
|
||||||
import Vervis.Widget.Person
|
import Vervis.Widget.Person
|
||||||
|
|
||||||
|
selectDiscussionID deckHash taskHash = do
|
||||||
|
(_, _, Entity _ ticket, _, _) <- getTicket404 deckHash taskHash
|
||||||
|
return $ ticketDiscuss ticket
|
||||||
|
|
||||||
getTicketR :: KeyHashid Deck -> KeyHashid TicketDeck -> Handler TypedContent
|
getTicketR :: KeyHashid Deck -> KeyHashid TicketDeck -> Handler TypedContent
|
||||||
getTicketR deckHash ticketHash = do
|
getTicketR deckHash ticketHash = do
|
||||||
(ticket, author, resolve) <- runDB $ do
|
(ticket, author, resolve) <- runDB $ do
|
||||||
|
@ -275,7 +277,7 @@ getTicketR deckHash ticketHash = do
|
||||||
discussionW
|
discussionW
|
||||||
(return $ ticketDiscuss ticket)
|
(return $ ticketDiscuss ticket)
|
||||||
(TicketReplyR deckHash ticketHash)
|
(TicketReplyR deckHash ticketHash)
|
||||||
(ReplyR . hashMessageKey)
|
(TicketReplyOnR deckHash ticketHash . hashMessageKey)
|
||||||
cRelevant <- newIdent
|
cRelevant <- newIdent
|
||||||
cIrrelevant <- newIdent
|
cIrrelevant <- newIdent
|
||||||
let relevant filt =
|
let relevant filt =
|
||||||
|
@ -293,15 +295,13 @@ getTicketR deckHash ticketHash = do
|
||||||
|
|
||||||
getTicketDiscussionR
|
getTicketDiscussionR
|
||||||
:: KeyHashid Deck -> KeyHashid TicketDeck -> Handler TypedContent
|
:: KeyHashid Deck -> KeyHashid TicketDeck -> Handler TypedContent
|
||||||
getTicketDiscussionR _ _ = do
|
getTicketDiscussionR deckHash taskHash = do
|
||||||
error "Temporarily disabled"
|
hashMsg <- getEncodeKeyHashid
|
||||||
{-
|
serveDiscussion
|
||||||
encodeHid <- getEncodeKeyHashid
|
(TicketDiscussionR deckHash taskHash)
|
||||||
getDiscussion
|
(TicketReplyOnR deckHash taskHash . hashMsg)
|
||||||
(ProjectTicketReplyR shar proj ltkhid . encodeHid)
|
(TicketReplyR deckHash taskHash)
|
||||||
(ProjectTicketTopReplyR shar proj ltkhid)
|
(selectDiscussionID deckHash taskHash)
|
||||||
(selectDiscussionId shar proj ltkhid)
|
|
||||||
-}
|
|
||||||
|
|
||||||
getTicketEventsR
|
getTicketEventsR
|
||||||
:: KeyHashid Deck -> KeyHashid TicketDeck -> Handler TypedContent
|
:: KeyHashid Deck -> KeyHashid TicketDeck -> Handler TypedContent
|
||||||
|
@ -426,22 +426,49 @@ postTicketFollowR _ = error "Temporarily disabled"
|
||||||
postTicketUnfollowR :: KeyHashid Deck -> KeyHashid TicketDeck -> Handler ()
|
postTicketUnfollowR :: KeyHashid Deck -> KeyHashid TicketDeck -> Handler ()
|
||||||
postTicketUnfollowR _ = error "Temporarily disabled"
|
postTicketUnfollowR _ = error "Temporarily disabled"
|
||||||
|
|
||||||
|
getTicketReplyR :: KeyHashid Deck -> KeyHashid TicketDeck -> Handler Html
|
||||||
|
getTicketReplyR deckHash taskHash =
|
||||||
|
getTopReply $ TicketReplyR deckHash taskHash
|
||||||
|
|
||||||
postTicketReplyR :: KeyHashid Deck -> KeyHashid TicketDeck -> Handler Html
|
postTicketReplyR :: KeyHashid Deck -> KeyHashid TicketDeck -> Handler Html
|
||||||
postTicketReplyR _ _ = error "Temporarily disabled"
|
postTicketReplyR deckHash taskHash =
|
||||||
{-
|
postReply
|
||||||
hLocal <- getsYesod $ appInstanceHost . appSettings
|
(TicketReplyR deckHash taskHash)
|
||||||
postTopReply
|
[LocalActorDeck deckHash]
|
||||||
hLocal
|
[ LocalStageDeckFollowers deckHash
|
||||||
[ProjectR shr prj]
|
, LocalStageTicketFollowers deckHash taskHash
|
||||||
[ ProjectFollowersR shr prj
|
|
||||||
, ProjectTicketParticipantsR shr prj ltkhid
|
|
||||||
, ProjectTicketTeamR shr prj ltkhid
|
|
||||||
]
|
]
|
||||||
(ProjectTicketR shr prj ltkhid)
|
(TicketR deckHash taskHash)
|
||||||
(ProjectR shr prj)
|
Nothing
|
||||||
(ProjectTicketDiscussionR shr prj ltkhid)
|
|
||||||
(const $ ProjectTicketR shr prj ltkhid)
|
getTicketReplyOnR
|
||||||
-}
|
:: KeyHashid Deck
|
||||||
|
-> KeyHashid TicketDeck
|
||||||
|
-> KeyHashid Message
|
||||||
|
-> Handler Html
|
||||||
|
getTicketReplyOnR deckHash taskHash msgHash = do
|
||||||
|
msgID <- decodeKeyHashid404 msgHash
|
||||||
|
hashMsg <- getEncodeKeyHashid
|
||||||
|
getReply
|
||||||
|
(TicketReplyOnR deckHash taskHash . hashMsg)
|
||||||
|
(selectDiscussionID deckHash taskHash)
|
||||||
|
msgID
|
||||||
|
|
||||||
|
postTicketReplyOnR
|
||||||
|
:: KeyHashid Deck
|
||||||
|
-> KeyHashid TicketDeck
|
||||||
|
-> KeyHashid Message
|
||||||
|
-> Handler Html
|
||||||
|
postTicketReplyOnR deckHash taskHash msgHash = do
|
||||||
|
msgID <- decodeKeyHashid404 msgHash
|
||||||
|
postReply
|
||||||
|
(TicketReplyOnR deckHash taskHash msgHash)
|
||||||
|
[LocalActorDeck deckHash]
|
||||||
|
[ LocalStageDeckFollowers deckHash
|
||||||
|
, LocalStageTicketFollowers deckHash taskHash
|
||||||
|
]
|
||||||
|
(TicketR deckHash taskHash)
|
||||||
|
(Just (selectDiscussionID deckHash taskHash, msgID))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -803,58 +830,6 @@ postClaimRequestsTicketR shr prj ltkhid = do
|
||||||
setMessage "Submission failed, see errors below."
|
setMessage "Submission failed, see errors below."
|
||||||
defaultLayout $(widgetFile "ticket/claim-request/new")
|
defaultLayout $(widgetFile "ticket/claim-request/new")
|
||||||
|
|
||||||
selectDiscussionId
|
|
||||||
:: ShrIdent -> PrjIdent -> KeyHashid LocalTicket -> AppDB DiscussionId
|
|
||||||
selectDiscussionId shr prj ltkhid = do
|
|
||||||
(_es, _ej, _et, Entity _ lticket, _etcl, _etpl, _author, _) <- getProjectTicket404 shr prj ltkhid
|
|
||||||
return $ localTicketDiscuss lticket
|
|
||||||
|
|
||||||
getMessageR :: ShrIdent -> KeyHashid LocalMessage -> Handler TypedContent
|
|
||||||
getMessageR shr hid = do
|
|
||||||
lmid <- decodeKeyHashid404 hid
|
|
||||||
getDiscussionMessage shr lmid
|
|
||||||
|
|
||||||
postProjectTicketMessageR
|
|
||||||
:: ShrIdent
|
|
||||||
-> PrjIdent
|
|
||||||
-> KeyHashid LocalTicket
|
|
||||||
-> KeyHashid Message
|
|
||||||
-> Handler Html
|
|
||||||
postProjectTicketMessageR shr prj ltkhid mkhid = do
|
|
||||||
encodeHid <- getEncodeKeyHashid
|
|
||||||
mid <- decodeKeyHashid404 mkhid
|
|
||||||
hLocal <- getsYesod $ appInstanceHost . appSettings
|
|
||||||
postReply
|
|
||||||
hLocal
|
|
||||||
[ProjectR shr prj]
|
|
||||||
[ ProjectFollowersR shr prj
|
|
||||||
, ProjectTicketParticipantsR shr prj ltkhid
|
|
||||||
, ProjectTicketTeamR shr prj ltkhid
|
|
||||||
]
|
|
||||||
(ProjectTicketR shr prj ltkhid)
|
|
||||||
(ProjectR shr prj)
|
|
||||||
(ProjectTicketReplyR shr prj ltkhid . encodeHid)
|
|
||||||
(ProjectTicketMessageR shr prj ltkhid . encodeHid)
|
|
||||||
(const $ ProjectTicketR shr prj ltkhid)
|
|
||||||
(selectDiscussionId shr prj ltkhid)
|
|
||||||
mid
|
|
||||||
|
|
||||||
getProjectTicketTopReplyR
|
|
||||||
:: ShrIdent -> PrjIdent -> KeyHashid LocalTicket -> Handler Html
|
|
||||||
getProjectTicketTopReplyR shr prj ltkhid =
|
|
||||||
getTopReply $ ProjectTicketDiscussionR shr prj ltkhid
|
|
||||||
|
|
||||||
getProjectTicketReplyR
|
|
||||||
:: ShrIdent -> PrjIdent -> KeyHashid LocalTicket -> KeyHashid Message -> Handler Html
|
|
||||||
getProjectTicketReplyR shr prj ltkhid mkhid = do
|
|
||||||
encodeHid <- getEncodeKeyHashid
|
|
||||||
mid <- decodeKeyHashid404 mkhid
|
|
||||||
getReply
|
|
||||||
(ProjectTicketReplyR shr prj ltkhid . encodeHid)
|
|
||||||
(ProjectTicketMessageR shr prj ltkhid . encodeHid)
|
|
||||||
(selectDiscussionId shr prj ltkhid)
|
|
||||||
mid
|
|
||||||
|
|
||||||
postProjectTicketDepsR
|
postProjectTicketDepsR
|
||||||
:: ShrIdent -> PrjIdent -> KeyHashid LocalTicket -> Handler Html
|
:: ShrIdent -> PrjIdent -> KeyHashid LocalTicket -> Handler Html
|
||||||
postProjectTicketDepsR _shr _prj _ltkhid = error "Temporarily disabled"
|
postProjectTicketDepsR _shr _prj _ltkhid = error "Temporarily disabled"
|
||||||
|
@ -1104,13 +1079,6 @@ getSharerTicketR shr talkhid = do
|
||||||
where
|
where
|
||||||
here = SharerTicketR shr talkhid
|
here = SharerTicketR shr talkhid
|
||||||
|
|
||||||
getSharerTicketDiscussionR
|
|
||||||
:: ShrIdent -> KeyHashid TicketAuthorLocal -> Handler TypedContent
|
|
||||||
getSharerTicketDiscussionR shr talkhid =
|
|
||||||
getRepliesCollection (SharerTicketDiscussionR shr talkhid) $ do
|
|
||||||
(_, Entity _ lt, _, _, _) <- getSharerTicket404 shr talkhid
|
|
||||||
return $ localTicketDiscuss lt
|
|
||||||
|
|
||||||
getSharerTicketDepsR
|
getSharerTicketDepsR
|
||||||
:: ShrIdent -> KeyHashid TicketAuthorLocal -> Handler TypedContent
|
:: ShrIdent -> KeyHashid TicketAuthorLocal -> Handler TypedContent
|
||||||
getSharerTicketDepsR shr talkhid =
|
getSharerTicketDepsR shr talkhid =
|
||||||
|
|
|
@ -17,9 +17,9 @@ module Vervis.Persist.Discussion
|
||||||
( MessageTreeNodeAuthor (..)
|
( MessageTreeNodeAuthor (..)
|
||||||
, MessageTreeNode (..)
|
, MessageTreeNode (..)
|
||||||
, getDiscussionTree
|
, getDiscussionTree
|
||||||
--, getRepliesCollection
|
|
||||||
, getLocalParentMessageId
|
, getLocalParentMessageId
|
||||||
, getMessageParent
|
, getMessageParent
|
||||||
|
, getMessageFromID
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
|
|
||||||
|
@ -35,8 +35,9 @@ import Data.Maybe (isNothing, mapMaybe)
|
||||||
import Data.Text (Text)
|
import Data.Text (Text)
|
||||||
import Data.Tree (Forest)
|
import Data.Tree (Forest)
|
||||||
import Database.Esqueleto hiding (isNothing)
|
import Database.Esqueleto hiding (isNothing)
|
||||||
|
import Yesod.Core
|
||||||
import Yesod.Core.Content
|
import Yesod.Core.Content
|
||||||
import Yesod.Persist.Core (runDB)
|
import Yesod.Persist.Core
|
||||||
|
|
||||||
import qualified Data.HashMap.Lazy as M (fromList, lookup)
|
import qualified Data.HashMap.Lazy as M (fromList, lookup)
|
||||||
import qualified Database.Esqueleto as E
|
import qualified Database.Esqueleto as E
|
||||||
|
@ -71,8 +72,29 @@ data MessageTreeNode = MessageTreeNode
|
||||||
, mtnAuthor :: MessageTreeNodeAuthor
|
, mtnAuthor :: MessageTreeNodeAuthor
|
||||||
}
|
}
|
||||||
|
|
||||||
getMessages :: AppDB DiscussionId -> Handler [MessageTreeNode]
|
getLocalAuthor lmid aid name = do
|
||||||
getMessages getdid = runDB $ do
|
authorByKey <- getLocalActor aid
|
||||||
|
code <-
|
||||||
|
case authorByKey of
|
||||||
|
LocalActorPerson personID -> do
|
||||||
|
person <- getJust personID
|
||||||
|
return $ "~" <> username2text (personUsername person)
|
||||||
|
LocalActorGroup groupID -> do
|
||||||
|
groupHash <- encodeKeyHashid groupID
|
||||||
|
return $ "&" <> keyHashidText groupHash
|
||||||
|
LocalActorRepo repoID -> do
|
||||||
|
repoHash <- encodeKeyHashid repoID
|
||||||
|
return $ "^" <> keyHashidText repoHash
|
||||||
|
LocalActorDeck deckID -> do
|
||||||
|
deckHash <- encodeKeyHashid deckID
|
||||||
|
return $ "=" <> keyHashidText deckHash
|
||||||
|
LocalActorLoom loomID -> do
|
||||||
|
loomHash <- encodeKeyHashid loomID
|
||||||
|
return $ "+" <> keyHashidText loomHash
|
||||||
|
return $ MessageTreeNodeLocal lmid authorByKey code name
|
||||||
|
|
||||||
|
getAllMessages :: AppDB DiscussionId -> Handler [MessageTreeNode]
|
||||||
|
getAllMessages getdid = runDB $ do
|
||||||
did <- getdid
|
did <- getdid
|
||||||
l <- select $ from $ \ (lm `InnerJoin` m `InnerJoin` a) -> do
|
l <- select $ from $ \ (lm `InnerJoin` m `InnerJoin` a) -> do
|
||||||
on $ lm ^. LocalMessageAuthor ==. a ^. ActorId
|
on $ lm ^. LocalMessageAuthor ==. a ^. ActorId
|
||||||
|
@ -103,25 +125,8 @@ getMessages getdid = runDB $ do
|
||||||
return $ locals ++ remotes
|
return $ locals ++ remotes
|
||||||
where
|
where
|
||||||
mklocal (Entity mid m, Value lmid, Value aid, Value name) = do
|
mklocal (Entity mid m, Value lmid, Value aid, Value name) = do
|
||||||
authorByKey <- getLocalActor aid
|
author <- getLocalAuthor lmid aid name
|
||||||
code <-
|
return $ MessageTreeNode mid m author
|
||||||
case authorByKey of
|
|
||||||
LocalActorPerson personID -> do
|
|
||||||
person <- getJust personID
|
|
||||||
return $ "~" <> username2text (personUsername person)
|
|
||||||
LocalActorGroup groupID -> do
|
|
||||||
groupHash <- encodeKeyHashid groupID
|
|
||||||
return $ "&" <> keyHashidText groupHash
|
|
||||||
LocalActorRepo repoID -> do
|
|
||||||
repoHash <- encodeKeyHashid repoID
|
|
||||||
return $ "^" <> keyHashidText repoHash
|
|
||||||
LocalActorDeck deckID -> do
|
|
||||||
deckHash <- encodeKeyHashid deckID
|
|
||||||
return $ "=" <> keyHashidText deckHash
|
|
||||||
LocalActorLoom loomID -> do
|
|
||||||
loomHash <- encodeKeyHashid loomID
|
|
||||||
return $ "+" <> keyHashidText loomHash
|
|
||||||
return $ MessageTreeNode mid m $ MessageTreeNodeLocal lmid authorByKey code name
|
|
||||||
mkremote (Entity mid m, Value h, Value luMsg, Value luAuthor, Value name) =
|
mkremote (Entity mid m, Value h, Value luMsg, Value luAuthor, Value name) =
|
||||||
MessageTreeNode mid m $ MessageTreeNodeRemote h luMsg luAuthor name
|
MessageTreeNode mid m $ MessageTreeNodeRemote h luMsg luAuthor name
|
||||||
|
|
||||||
|
@ -149,57 +154,10 @@ sortByTime = sortForestOn $ messageCreated . mtnMessage
|
||||||
-- | Get the tree of messages in a given discussion, with siblings sorted from
|
-- | Get the tree of messages in a given discussion, with siblings sorted from
|
||||||
-- old to new.
|
-- old to new.
|
||||||
getDiscussionTree :: AppDB DiscussionId -> Handler (Forest MessageTreeNode)
|
getDiscussionTree :: AppDB DiscussionId -> Handler (Forest MessageTreeNode)
|
||||||
getDiscussionTree getdid = sortByTime . discussionTree <$> getMessages getdid
|
getDiscussionTree getdid =
|
||||||
|
sortByTime . discussionTree <$> getAllMessages getdid
|
||||||
|
|
||||||
{-
|
getMessageFromRoute
|
||||||
getRepliesCollection :: Route App -> AppDB DiscussionId -> Handler TypedContent
|
|
||||||
getRepliesCollection here getDiscussionId404 = do
|
|
||||||
(locals, remotes) <- runDB $ do
|
|
||||||
did <- getDiscussionId404
|
|
||||||
(,) <$> selectLocals did <*> selectRemotes did
|
|
||||||
encodeRouteLocal <- getEncodeRouteLocal
|
|
||||||
encodeRouteHome <- getEncodeRouteHome
|
|
||||||
encodeHid <- getEncodeKeyHashid
|
|
||||||
hashPerson <- getEncodeKeyHashid
|
|
||||||
let localUri' = localUri hashPerson encodeRouteHome encodeHid
|
|
||||||
replies = Collection
|
|
||||||
{ collectionId = encodeRouteLocal here
|
|
||||||
, collectionType = CollectionTypeUnordered
|
|
||||||
, collectionTotalItems = Just $ length locals + length remotes
|
|
||||||
, collectionCurrent = Nothing
|
|
||||||
, collectionFirst = Nothing
|
|
||||||
, collectionLast = Nothing
|
|
||||||
, collectionItems =
|
|
||||||
map localUri' locals ++ map remoteUri remotes
|
|
||||||
}
|
|
||||||
provideHtmlAndAP replies $ redirectToPrettyJSON here
|
|
||||||
where
|
|
||||||
selectLocals did =
|
|
||||||
E.select $ E.from $
|
|
||||||
\ (m `E.InnerJoin` lm) -> do
|
|
||||||
E.on $ m E.^. MessageId E.==. lm E.^. LocalMessageRest
|
|
||||||
E.where_ $
|
|
||||||
m E.^. MessageRoot E.==. E.val did E.&&.
|
|
||||||
E.isNothing (m E.^. MessageParent) E.&&.
|
|
||||||
E.isNothing (lm E.^. LocalMessageUnlinkedParent)
|
|
||||||
return (lm E.^. LocalMessageAuthor, lm E.^. LocalMessageId)
|
|
||||||
selectRemotes did =
|
|
||||||
E.select $ E.from $
|
|
||||||
\ (m `E.InnerJoin` rm `E.InnerJoin` ro `E.InnerJoin` i) -> do
|
|
||||||
E.on $ ro E.^. RemoteObjectInstance E.==. i E.^. InstanceId
|
|
||||||
E.on $ rm E.^. RemoteMessageIdent E.==. ro E.^. RemoteObjectId
|
|
||||||
E.on $ m E.^. MessageId E.==. rm E.^. RemoteMessageRest
|
|
||||||
E.where_ $
|
|
||||||
m E.^. MessageRoot E.==. E.val did E.&&.
|
|
||||||
E.isNothing (m E.^. MessageParent) E.&&.
|
|
||||||
E.isNothing (rm E.^. RemoteMessageLostParent)
|
|
||||||
return (i E.^. InstanceHost, ro E.^. RemoteObjectIdent)
|
|
||||||
localUri hashPerson encR encH (E.Value pid, E.Value lmid) =
|
|
||||||
encR $ PersonMessageR (hashPerson pid) (encH lmid)
|
|
||||||
remoteUri (E.Value h, E.Value lu) = ObjURI h lu
|
|
||||||
-}
|
|
||||||
|
|
||||||
getMessage
|
|
||||||
:: LocalActorBy Key
|
:: LocalActorBy Key
|
||||||
-> LocalMessageId
|
-> LocalMessageId
|
||||||
-> ExceptT Text AppDB
|
-> ExceptT Text AppDB
|
||||||
|
@ -208,7 +166,7 @@ getMessage
|
||||||
, Entity LocalMessage
|
, Entity LocalMessage
|
||||||
, Entity Message
|
, Entity Message
|
||||||
)
|
)
|
||||||
getMessage authorByKey localMsgID = do
|
getMessageFromRoute authorByKey localMsgID = do
|
||||||
authorByEntity <- do
|
authorByEntity <- do
|
||||||
maybeActor <- lift $ getLocalActorEntity authorByKey
|
maybeActor <- lift $ getLocalActorEntity authorByKey
|
||||||
fromMaybeE maybeActor "No such author in DB"
|
fromMaybeE maybeActor "No such author in DB"
|
||||||
|
@ -233,7 +191,7 @@ getLocalParentMessageId
|
||||||
-> (LocalActorBy Key, LocalMessageId)
|
-> (LocalActorBy Key, LocalMessageId)
|
||||||
-> ExceptT Text AppDB MessageId
|
-> ExceptT Text AppDB MessageId
|
||||||
getLocalParentMessageId discussionID (authorByKey, localMsgID) = do
|
getLocalParentMessageId discussionID (authorByKey, localMsgID) = do
|
||||||
(_, _, _, Entity msgID msg) <- getMessage authorByKey localMsgID
|
(_, _, _, Entity msgID msg) <- getMessageFromRoute authorByKey localMsgID
|
||||||
unless (messageRoot msg == discussionID) $
|
unless (messageRoot msg == discussionID) $
|
||||||
throwE "Local parent belongs to a different discussion"
|
throwE "Local parent belongs to a different discussion"
|
||||||
return msgID
|
return msgID
|
||||||
|
@ -259,3 +217,30 @@ getMessageParent did (Right p@(ObjURI hParent luParent)) = do
|
||||||
throwE "Remote parent belongs to a different discussion"
|
throwE "Remote parent belongs to a different discussion"
|
||||||
return mid
|
return mid
|
||||||
Nothing -> return $ Right p
|
Nothing -> return $ Right p
|
||||||
|
|
||||||
|
getMessageFromID :: AppDB DiscussionId -> MessageId -> AppDB MessageTreeNode
|
||||||
|
getMessageFromID getdid mid = do
|
||||||
|
did <- getdid
|
||||||
|
m <- get404 mid
|
||||||
|
unless (messageRoot m == did) notFound
|
||||||
|
mlocal <- getBy $ UniqueLocalMessage mid
|
||||||
|
mremote <- getBy $ UniqueRemoteMessage mid
|
||||||
|
author <- case (mlocal, mremote) of
|
||||||
|
(Nothing, Nothing) -> fail "Message with no author"
|
||||||
|
(Just _, Just _) -> fail "Message used as both local and remote"
|
||||||
|
(Just (Entity lmid lm), Nothing) -> do
|
||||||
|
let actorID = localMessageAuthor lm
|
||||||
|
name <- actorName <$> getJust actorID
|
||||||
|
getLocalAuthor lmid actorID name
|
||||||
|
(Nothing, Just (Entity _rmid rm)) -> do
|
||||||
|
ra <- getJust $ remoteMessageAuthor rm
|
||||||
|
roA <- getJust $ remoteActorIdent ra
|
||||||
|
roM <- getJust $ remoteMessageIdent rm
|
||||||
|
i <- getJust $ remoteObjectInstance roA
|
||||||
|
return $
|
||||||
|
MessageTreeNodeRemote
|
||||||
|
(instanceHost i)
|
||||||
|
(remoteObjectIdent roM)
|
||||||
|
(remoteObjectIdent roA)
|
||||||
|
(remoteActorName ra)
|
||||||
|
return $ MessageTreeNode mid m author
|
||||||
|
|
|
@ -14,11 +14,10 @@
|
||||||
-}
|
-}
|
||||||
|
|
||||||
module Vervis.Web.Discussion
|
module Vervis.Web.Discussion
|
||||||
( getDiscussion
|
( serveDiscussion
|
||||||
--, getTopReply
|
, getTopReply
|
||||||
--, postTopReply
|
, getReply
|
||||||
--, getReply
|
, postReply
|
||||||
--, postReply
|
|
||||||
, serveMessage
|
, serveMessage
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
|
@ -42,6 +41,7 @@ import Yesod.Form.Types (FormResult (..))
|
||||||
import Yesod.Persist.Core (runDB, get404, getBy404)
|
import Yesod.Persist.Core (runDB, get404, getBy404)
|
||||||
|
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
|
import qualified Database.Esqueleto as E
|
||||||
|
|
||||||
import Data.Aeson.Encode.Pretty.ToEncoding
|
import Data.Aeson.Encode.Pretty.ToEncoding
|
||||||
import Database.Persist.JSON
|
import Database.Persist.JSON
|
||||||
|
@ -57,6 +57,7 @@ import qualified Web.ActivityPub as AP
|
||||||
|
|
||||||
import Data.Either.Local
|
import Data.Either.Local
|
||||||
import Database.Persist.Local
|
import Database.Persist.Local
|
||||||
|
import Yesod.Form.Local
|
||||||
import Yesod.Persist.Local
|
import Yesod.Persist.Local
|
||||||
|
|
||||||
import Vervis.API
|
import Vervis.API
|
||||||
|
@ -73,41 +74,65 @@ import Vervis.Settings
|
||||||
import Vervis.Ticket
|
import Vervis.Ticket
|
||||||
import Vervis.Widget.Discussion
|
import Vervis.Widget.Discussion
|
||||||
|
|
||||||
getDiscussion
|
import qualified Vervis.Client as C
|
||||||
:: (MessageId -> Route App)
|
|
||||||
|
getRepliesCollection
|
||||||
|
:: Route App -> AppDB DiscussionId -> Handler (AP.Collection FedURI URIMode)
|
||||||
|
getRepliesCollection here getDiscussionId404 = do
|
||||||
|
(locals, remotes) <- runDB $ do
|
||||||
|
did <- getDiscussionId404
|
||||||
|
(,) <$> selectLocals did <*> selectRemotes did
|
||||||
|
encodeRouteLocal <- getEncodeRouteLocal
|
||||||
|
encodeRouteHome <- getEncodeRouteHome
|
||||||
|
hashMsg <- getEncodeKeyHashid
|
||||||
|
hashActor <- getHashLocalActor
|
||||||
|
let localUri (authorByKey, localMsgID) =
|
||||||
|
encodeRouteHome $
|
||||||
|
messageRoute (hashActor authorByKey) (hashMsg localMsgID)
|
||||||
|
return AP.Collection
|
||||||
|
{ AP.collectionId = encodeRouteLocal here
|
||||||
|
, AP.collectionType = AP.CollectionTypeUnordered
|
||||||
|
, AP.collectionTotalItems = Just $ length locals + length remotes
|
||||||
|
, AP.collectionCurrent = Nothing
|
||||||
|
, AP.collectionFirst = Nothing
|
||||||
|
, AP.collectionLast = Nothing
|
||||||
|
, AP.collectionItems =
|
||||||
|
map localUri locals ++ map remoteUri remotes
|
||||||
|
}
|
||||||
|
where
|
||||||
|
selectLocals did = do
|
||||||
|
locals <- E.select $ E.from $ \ (m `E.InnerJoin` lm) -> do
|
||||||
|
E.on $ m E.^. MessageId E.==. lm E.^. LocalMessageRest
|
||||||
|
E.where_ $
|
||||||
|
m E.^. MessageRoot E.==. E.val did E.&&.
|
||||||
|
E.isNothing (m E.^. MessageParent) E.&&.
|
||||||
|
E.isNothing (lm E.^. LocalMessageUnlinkedParent)
|
||||||
|
return (lm E.^. LocalMessageAuthor, lm E.^. LocalMessageId)
|
||||||
|
for locals $ \ (E.Value actorID, E.Value localMsgID) -> do
|
||||||
|
actorByKey <- getLocalActor actorID
|
||||||
|
return (actorByKey, localMsgID)
|
||||||
|
selectRemotes did =
|
||||||
|
E.select $ E.from $
|
||||||
|
\ (m `E.InnerJoin` rm `E.InnerJoin` ro `E.InnerJoin` i) -> do
|
||||||
|
E.on $ ro E.^. RemoteObjectInstance E.==. i E.^. InstanceId
|
||||||
|
E.on $ rm E.^. RemoteMessageIdent E.==. ro E.^. RemoteObjectId
|
||||||
|
E.on $ m E.^. MessageId E.==. rm E.^. RemoteMessageRest
|
||||||
|
E.where_ $
|
||||||
|
m E.^. MessageRoot E.==. E.val did E.&&.
|
||||||
|
E.isNothing (m E.^. MessageParent) E.&&.
|
||||||
|
E.isNothing (rm E.^. RemoteMessageLostParent)
|
||||||
|
return (i E.^. InstanceHost, ro E.^. RemoteObjectIdent)
|
||||||
|
remoteUri (E.Value h, E.Value lu) = ObjURI h lu
|
||||||
|
|
||||||
|
serveDiscussion
|
||||||
|
:: Route App
|
||||||
|
-> (MessageId -> Route App)
|
||||||
-> Route App
|
-> Route App
|
||||||
-> AppDB DiscussionId
|
-> AppDB DiscussionId
|
||||||
-> Handler Html
|
-> Handler TypedContent
|
||||||
getDiscussion reply topic getdid =
|
serveDiscussion here reply topic getdid = do
|
||||||
defaultLayout $ discussionW getdid topic reply
|
replies <- getRepliesCollection here getdid
|
||||||
|
provideHtmlAndAP replies (discussionW getdid topic reply)
|
||||||
{-
|
|
||||||
getNode :: AppDB DiscussionId -> MessageId -> AppDB MessageTreeNode
|
|
||||||
getNode getdid mid = do
|
|
||||||
did <- getdid
|
|
||||||
m <- get404 mid
|
|
||||||
unless (messageRoot m == did) notFound
|
|
||||||
mlocal <- getBy $ UniqueLocalMessage mid
|
|
||||||
mremote <- getBy $ UniqueRemoteMessage mid
|
|
||||||
author <- case (mlocal, mremote) of
|
|
||||||
(Nothing, Nothing) -> fail "Message with no author"
|
|
||||||
(Just _, Just _) -> fail "Message used as both local and remote"
|
|
||||||
(Just (Entity lmid lm), Nothing) -> do
|
|
||||||
p <- getJust $ localMessageAuthor lm
|
|
||||||
s <- getJust $ personIdent p
|
|
||||||
return $ MessageTreeNodeLocal lmid s
|
|
||||||
(Nothing, Just (Entity _rmid rm)) -> do
|
|
||||||
ra <- getJust $ remoteMessageAuthor rm
|
|
||||||
roA <- getJust $ remoteActorIdent ra
|
|
||||||
roM <- getJust $ remoteMessageIdent rm
|
|
||||||
i <- getJust $ remoteObjectInstance roA
|
|
||||||
return $
|
|
||||||
MessageTreeNodeRemote
|
|
||||||
(instanceHost i)
|
|
||||||
(remoteObjectIdent roM)
|
|
||||||
(remoteObjectIdent roA)
|
|
||||||
(remoteActorName ra)
|
|
||||||
return $ MessageTreeNode mid m author
|
|
||||||
|
|
||||||
{-
|
{-
|
||||||
getNodeL :: AppDB DiscussionId -> LocalMessageId -> AppDB MessageTreeNode
|
getNodeL :: AppDB DiscussionId -> LocalMessageId -> AppDB MessageTreeNode
|
||||||
|
@ -127,111 +152,68 @@ getTopReply replyP = do
|
||||||
((_result, widget), enctype) <- runFormPost newMessageForm
|
((_result, widget), enctype) <- runFormPost newMessageForm
|
||||||
defaultLayout $(widgetFile "discussion/top-reply")
|
defaultLayout $(widgetFile "discussion/top-reply")
|
||||||
|
|
||||||
postTopReply
|
getReply'
|
||||||
:: Host
|
|
||||||
-> [Route App]
|
|
||||||
-> [Route App]
|
|
||||||
-> Route App
|
|
||||||
-> Route App
|
|
||||||
-> Route App
|
|
||||||
-> (LocalMessageId -> Route App)
|
|
||||||
-> Handler Html
|
|
||||||
postTopReply hDest recipsA recipsC context recipF replyP after = do
|
|
||||||
((result, widget), enctype) <- runFormPost newMessageForm
|
|
||||||
(eperson, sharer) <- do
|
|
||||||
ep@(Entity _ p) <- requireVerifiedAuth
|
|
||||||
s <- runDB $ get404 (personIdent p)
|
|
||||||
return (ep, s)
|
|
||||||
let shrAuthor = sharerIdent sharer
|
|
||||||
eobiid <- runExceptT $ do
|
|
||||||
msg <- case result of
|
|
||||||
FormMissing -> throwE "Field(s) missing."
|
|
||||||
FormFailure _l -> throwE "Message submission failed, see errors below."
|
|
||||||
FormSuccess nm ->
|
|
||||||
return $ TextPandocMarkdown $ T.filter (/= '\r') $ nmContent nm
|
|
||||||
note <- ExceptT $ createThread shrAuthor msg hDest recipsA recipsC context
|
|
||||||
noteC eperson sharer note
|
|
||||||
case eobiid of
|
|
||||||
Left e -> do
|
|
||||||
setMessage $ toHtml e
|
|
||||||
defaultLayout $(widgetFile "discussion/top-reply")
|
|
||||||
Right obiid -> do
|
|
||||||
setMessage "Message submitted."
|
|
||||||
|
|
||||||
encodeRouteFed <- getEncodeRouteFed
|
|
||||||
let encodeRecipRoute = encodeRouteFed hDest
|
|
||||||
(summary, audience, follow) <- C.follow shrAuthor (encodeRecipRoute context) (encodeRecipRoute recipF) False
|
|
||||||
eobiidFollow <- runExceptT $ followC shrAuthor (Just summary) audience follow
|
|
||||||
case eobiidFollow of
|
|
||||||
Left e -> setMessage $ toHtml $ "Following failed: " <> e
|
|
||||||
Right _ -> return ()
|
|
||||||
|
|
||||||
mlmid <- runDB $ getKeyBy $ UniqueLocalMessageCreate obiid
|
|
||||||
case mlmid of
|
|
||||||
Nothing -> error "noteC succeeded but no lmid found for obiid"
|
|
||||||
Just lmid -> redirect $ after lmid
|
|
||||||
|
|
||||||
getReply
|
|
||||||
:: (MessageId -> Route App)
|
:: (MessageId -> Route App)
|
||||||
-> (MessageId -> Route App)
|
-> (MessageId -> Route App)
|
||||||
-> AppDB DiscussionId
|
-> AppDB DiscussionId
|
||||||
-> MessageId
|
-> MessageId
|
||||||
-> Handler Html
|
-> Handler Html
|
||||||
getReply replyG replyP getdid midParent = do
|
getReply' replyG replyP getdid midParent = do
|
||||||
mtn <- runDB $ getNode getdid midParent
|
mtn <- runDB $ getMessageFromID getdid midParent
|
||||||
now <- liftIO getCurrentTime
|
now <- liftIO getCurrentTime
|
||||||
((_result, widget), enctype) <- runFormPost newMessageForm
|
((_result, widget), enctype) <- runFormPost newMessageForm
|
||||||
defaultLayout $(widgetFile "discussion/reply")
|
defaultLayout $(widgetFile "discussion/reply")
|
||||||
|
|
||||||
postReply
|
getReply
|
||||||
:: Host
|
:: (MessageId -> Route App)
|
||||||
-> [Route App]
|
|
||||||
-> [Route App]
|
|
||||||
-> Route App
|
|
||||||
-> Route App
|
|
||||||
-> (MessageId -> Route App)
|
|
||||||
-> (MessageId -> Route App)
|
|
||||||
-> (LocalMessageId -> Route App)
|
|
||||||
-> AppDB DiscussionId
|
-> AppDB DiscussionId
|
||||||
-> MessageId
|
-> MessageId
|
||||||
-> Handler Html
|
-> Handler Html
|
||||||
postReply hDest recipsA recipsC context recipF replyG replyP after getdid midParent = do
|
getReply replyR = getReply' replyR replyR
|
||||||
((result, widget), enctype) <- runFormPost newMessageForm
|
|
||||||
(eperson, sharer) <- do
|
postReply
|
||||||
ep@(Entity _ p) <- requireVerifiedAuth
|
:: Route App
|
||||||
s <- runDB $ get404 (personIdent p)
|
-> [LocalActorBy KeyHashid]
|
||||||
return (ep, s)
|
-> [LocalStageBy KeyHashid]
|
||||||
let shrAuthor = sharerIdent sharer
|
-> Route App
|
||||||
eobiid <- runExceptT $ do
|
-> Maybe (AppDB DiscussionId, MessageId)
|
||||||
msg <- case result of
|
-> Handler Html
|
||||||
FormMissing -> throwE "Field(s) missing."
|
postReply formR actors stages topicR maybeParent = do
|
||||||
FormFailure _l -> throwE "Message submission failed, see errors below."
|
source <- runFormPostRedirect formR newMessageForm
|
||||||
FormSuccess nm ->
|
person@(Entity senderID sender) <- requireAuth
|
||||||
return $ TextPandocMarkdown $ T.filter (/= '\r') $ nmContent nm
|
senderHash <- encodeKeyHashid senderID
|
||||||
note <- ExceptT $ createReply shrAuthor msg hDest recipsA recipsC context midParent
|
errorOrCreate <- runExceptT $ do
|
||||||
noteC eperson sharer note
|
muParent <- for maybeParent $ \ (getdid, midParent) -> do
|
||||||
case eobiid of
|
MessageTreeNode _ _ author <-
|
||||||
|
lift $ runDB $ getMessageFromID getdid midParent
|
||||||
|
case author of
|
||||||
|
MessageTreeNodeLocal localMsgID authorByKey _ _ -> do
|
||||||
|
encodeRouteHome <- getEncodeRouteHome
|
||||||
|
localMsgHash <- encodeKeyHashid localMsgID
|
||||||
|
authorByHash <- hashLocalActor authorByKey
|
||||||
|
return $ encodeRouteHome $
|
||||||
|
messageRoute authorByHash localMsgHash
|
||||||
|
MessageTreeNodeRemote h _ luAuthor _ ->
|
||||||
|
return $ ObjURI h luAuthor
|
||||||
|
(maybeSummary, audience, note) <-
|
||||||
|
C.comment senderHash source actors stages topicR muParent
|
||||||
|
hLocal <- asksSite siteInstanceHost
|
||||||
|
let specific =
|
||||||
|
AP.CreateActivity $
|
||||||
|
AP.Create (AP.CreateNote hLocal note) Nothing
|
||||||
|
(localRecips, remoteRecips, fwdHosts, action) <-
|
||||||
|
lift $ C.makeServerInput Nothing maybeSummary audience specific
|
||||||
|
actor <- lift $ runDB $ getJust $ personActor sender
|
||||||
|
createNoteC
|
||||||
|
person actor Nothing localRecips remoteRecips fwdHosts
|
||||||
|
action note Nothing
|
||||||
|
case errorOrCreate of
|
||||||
Left e -> do
|
Left e -> do
|
||||||
setMessage $ toHtml e
|
setMessage $ toHtml e
|
||||||
mtn <- runDB $ getNode getdid midParent
|
redirect formR
|
||||||
now <- liftIO getCurrentTime
|
Right createID -> do
|
||||||
defaultLayout $(widgetFile "discussion/reply")
|
|
||||||
Right obiid -> do
|
|
||||||
setMessage "Message submitted."
|
setMessage "Message submitted."
|
||||||
|
redirect topicR
|
||||||
encodeRouteFed <- getEncodeRouteFed
|
|
||||||
let encodeRecipRoute = encodeRouteFed hDest
|
|
||||||
(summary, audience, follow) <- C.follow shrAuthor (encodeRecipRoute context) (encodeRecipRoute recipF) False
|
|
||||||
eobiidFollow <- runExceptT $ followC shrAuthor (Just summary) audience follow
|
|
||||||
case eobiidFollow of
|
|
||||||
Left e -> setMessage $ toHtml $ "Following failed: " <> e
|
|
||||||
Right _ -> return ()
|
|
||||||
|
|
||||||
mlmid <- runDB $ getKeyBy $ UniqueLocalMessageCreate obiid
|
|
||||||
case mlmid of
|
|
||||||
Nothing -> error "noteC succeeded but no lmid found for obiid"
|
|
||||||
Just lmid -> redirect $ after lmid
|
|
||||||
-}
|
|
||||||
|
|
||||||
serveMessage authorHash localMessageHash = do
|
serveMessage authorHash localMessageHash = do
|
||||||
authorID <- decodeKeyHashid404 authorHash
|
authorID <- decodeKeyHashid404 authorHash
|
||||||
|
|
12
th/routes
12
th/routes
|
@ -148,8 +148,6 @@
|
||||||
/people/#PersonKeyHashid/follow PersonFollowR POST
|
/people/#PersonKeyHashid/follow PersonFollowR POST
|
||||||
/people/#PersonKeyHashid/unfollow PersonUnfollowR POST
|
/people/#PersonKeyHashid/unfollow PersonUnfollowR POST
|
||||||
|
|
||||||
/reply/#MessageKeyHashid ReplyR POST
|
|
||||||
|
|
||||||
/people/#PersonKeyHashid/stamps/#SigKeyKeyHashid PersonStampR GET
|
/people/#PersonKeyHashid/stamps/#SigKeyKeyHashid PersonStampR GET
|
||||||
|
|
||||||
---- Group ------------------------------------------------------------------
|
---- Group ------------------------------------------------------------------
|
||||||
|
@ -236,9 +234,10 @@
|
||||||
-- /decks/#DeckKeyHashid/tickets/#TicketDeckKeyHashid/unclaim TicketUnclaimR POST
|
-- /decks/#DeckKeyHashid/tickets/#TicketDeckKeyHashid/unclaim TicketUnclaimR POST
|
||||||
-- /decks/#DeckKeyHashid/tickets/#TicketDeckKeyHashid/assign TicketAssignR GET POST
|
-- /decks/#DeckKeyHashid/tickets/#TicketDeckKeyHashid/assign TicketAssignR GET POST
|
||||||
-- /decks/#DeckKeyHashid/tickets/#TicketDeckKeyHashid/unassign TicketUnassignR POST
|
-- /decks/#DeckKeyHashid/tickets/#TicketDeckKeyHashid/unassign TicketUnassignR POST
|
||||||
/decks/#DeckKeyHashid/tickets/#TicketDeckKeyHashid/follow TicketFollowR POST
|
/decks/#DeckKeyHashid/tickets/#TicketDeckKeyHashid/follow TicketFollowR POST
|
||||||
/decks/#DeckKeyHashid/tickets/#TicketDeckKeyHashid/unfollow TicketUnfollowR POST
|
/decks/#DeckKeyHashid/tickets/#TicketDeckKeyHashid/unfollow TicketUnfollowR POST
|
||||||
/decks/#DeckKeyHashid/tickets/#TicketDeckKeyHashid/reply TicketReplyR POST
|
/decks/#DeckKeyHashid/tickets/#TicketDeckKeyHashid/reply TicketReplyR GET POST
|
||||||
|
/decks/#DeckKeyHashid/tickets/#TicketDeckKeyHashid/reply/#MessageKeyHashid TicketReplyOnR GET POST
|
||||||
|
|
||||||
---- Ticket Dependency -------------------------------------------------------
|
---- Ticket Dependency -------------------------------------------------------
|
||||||
|
|
||||||
|
@ -291,7 +290,8 @@
|
||||||
/looms/#LoomKeyHashid/cloths/#TicketLoomKeyHashid/apply ClothApplyR POST
|
/looms/#LoomKeyHashid/cloths/#TicketLoomKeyHashid/apply ClothApplyR POST
|
||||||
/looms/#LoomKeyHashid/cloths/#TicketLoomKeyHashid/follow ClothFollowR POST
|
/looms/#LoomKeyHashid/cloths/#TicketLoomKeyHashid/follow ClothFollowR POST
|
||||||
/looms/#LoomKeyHashid/cloths/#TicketLoomKeyHashid/unfollow ClothUnfollowR POST
|
/looms/#LoomKeyHashid/cloths/#TicketLoomKeyHashid/unfollow ClothUnfollowR POST
|
||||||
/looms/#LoomKeyHashid/cloths/#TicketLoomKeyHashid/reply ClothReplyR POST
|
/looms/#LoomKeyHashid/cloths/#TicketLoomKeyHashid/reply ClothReplyR GET POST
|
||||||
|
/looms/#LoomKeyHashid/cloths/#TicketLoomKeyHashid/reply/#MessageKeyHashid ClothReplyOnR GET POST
|
||||||
|
|
||||||
---- Cloth Dependency --------------------------------------------------------
|
---- Cloth Dependency --------------------------------------------------------
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue