UI: Group: Display parent and child invites & approve-remove buttons

This commit is contained in:
Pere Lev 2024-05-12 20:15:53 +03:00
parent 533fc60fe1
commit 74af2ea223
No known key found for this signature in database
GPG key ID: 5252C5C863E5E57D
3 changed files with 244 additions and 17 deletions

View file

@ -62,6 +62,7 @@ module Vervis.Handler.Group
where where
import Control.Applicative import Control.Applicative
import Control.Arrow ((&&&))
import Control.Monad import Control.Monad
import Control.Monad.Trans.Except import Control.Monad.Trans.Except
import Control.Monad.Trans.Maybe import Control.Monad.Trans.Maybe
@ -72,7 +73,7 @@ import Data.ByteString (ByteString)
import Data.Default.Class import Data.Default.Class
import Data.Foldable import Data.Foldable
import Data.List import Data.List
import Data.Maybe (fromMaybe) import Data.Maybe
import Data.Text (Text) import Data.Text (Text)
import Data.Time.Clock import Data.Time.Clock
import Data.Traversable import Data.Traversable
@ -416,15 +417,15 @@ getGroupChildrenR groupHash = do
actor <- getJust $ groupActor group actor <- getJust $ groupActor group
children <- getChildren groupID children <- getChildren groupID
return (actor, group, children) return (actor, group, children)
encodeRouteLocal <- getEncodeRouteLocal
encodeRouteHome <- getEncodeRouteHome encodeRouteHome <- getEncodeRouteHome
encodeRouteLocal <- getEncodeRouteLocal
hashGroup <- getEncodeKeyHashid hashGroup <- getEncodeKeyHashid
h <- asksSite siteInstanceHost h <- asksSite siteInstanceHost
let makeId (Left (childID, _)) = let makeId (Left (childID, _)) =
encodeRouteHome $ GroupR $ hashGroup childID encodeRouteHome $ GroupR $ hashGroup childID
makeId (Right (i, ro, _)) = makeId (Right (i, ro, _)) =
ObjURI (instanceHost i) (remoteObjectIdent ro) ObjURI (instanceHost i) (remoteObjectIdent ro)
makeItem (role, time, i) = AP.Relationship makeItem (role, time, i, _) = AP.Relationship
{ AP.relationshipId = Nothing { AP.relationshipId = Nothing
, AP.relationshipExtraTypes = [] , AP.relationshipExtraTypes = []
, AP.relationshipSubject = encodeRouteHome $ GroupR groupHash , AP.relationshipSubject = encodeRouteHome $ GroupR groupHash
@ -451,13 +452,13 @@ getGroupChildrenR groupHash = do
where where
getChildren groupID = fmap (sortOn $ view _2) $ liftA2 (++) getChildren groupID = fmap (sortOn $ view _2) $ liftA2 (++)
(map (\ (E.Value role, E.Value time, E.Value child, Entity _ actor) -> (map (\ (E.Value role, E.Value time, E.Value child, Entity _ actor, E.Value destID) ->
(role, time, Left (child, actor)) (role, time, Left (child, actor), destID)
) )
<$> getLocals groupID <$> getLocals groupID
) )
(map (\ (E.Value role, E.Value time, Entity _ i, Entity _ ro, Entity _ ra) -> (map (\ (E.Value role, E.Value time, Entity _ i, Entity _ ro, Entity _ ra, E.Value destID) ->
(role, time, Right (i, ro, ra)) (role, time, Right (i, ro, ra), destID)
) )
<$> getRemotes groupID <$> getRemotes groupID
) )
@ -478,6 +479,7 @@ getGroupChildrenR groupHash = do
, grant E.^. OutboxItemPublished , grant E.^. OutboxItemPublished
, topic E.^. DestTopicGroupChild , topic E.^. DestTopicGroupChild
, actor , actor
, dest E.^. DestId
) )
getRemotes groupID = getRemotes groupID =
@ -498,10 +500,80 @@ getGroupChildrenR groupHash = do
, i , i
, ro , ro
, ra , ra
, dest E.^. DestId
) )
getHtml groupID group actor children = do getHtml groupID group actor children = do
mp <- maybeAuthId
haveAdmin <- fmap isJust $ handlerToWidget $ runDB $ runMaybeT $ do
personID <- MaybeT $ pure mp
MaybeT $ getCapability personID (Left $ groupResource group) AP.RoleAdmin
((_, widgetAP), enctypeAP) <- runFormPost addChildForm
invites <- handlerToWidget $ runDB $ do
dests <- E.select $ E.from $ \ (dest `E.InnerJoin` holder `E.LeftOuterJoin` accept `E.LeftOuterJoin` delegl `E.LeftOuterJoin` delegr) -> do
E.on $ accept E.?. DestUsAcceptId E.==. delegr E.?. DestThemSendDelegatorRemoteDest
E.on $ accept E.?. DestUsAcceptId E.==. delegl E.?. DestThemSendDelegatorLocalDest
E.on $ E.just (dest E.^. DestId) E.==. accept E.?. DestUsAcceptDest
E.on $ dest E.^. DestId E.==. holder E.^. DestHolderGroupDest
E.where_ $
holder E.^. DestHolderGroupGroup E.==. E.val groupID E.&&.
E.isNothing (delegl E.?. DestThemSendDelegatorLocalId) E.&&.
E.isNothing (delegr E.?. DestThemSendDelegatorRemoteId)
E.orderBy [E.asc $ dest E.^. DestId]
return dest
for dests $ \ (Entity destID (Dest role)) -> do
child <- do
topic <- getDestTopic destID
bitraverse
(\ (_, e) -> do
jID <-
case e of
Right j -> pure j
Left _ -> error "I'm a Group but my child is a Project"
j <- getJust jID
actor <- getJust $ groupActor j
return (jID, actor)
)
(\ (_, actorID) -> getRemoteActorData actorID)
topic
accept <- isJust <$> getBy (UniqueDestUsAccept destID)
((inviter, time), us) <- do
usOrThem <-
requireEitherAlt
(getKeyBy $ UniqueDestOriginUs destID)
(getKeyBy $ UniqueDestOriginThem destID)
"Neither us nor them"
"Both us and them"
(addOrActor, us) <-
case usOrThem of
Left _usID -> (,True) <$>
requireEitherAlt
(fmap destUsGestureLocalActivity <$> getValBy (UniqueDestUsGestureLocal destID))
(fmap (destUsGestureRemoteActor &&& destUsGestureRemoteActivity) <$> getValBy (UniqueDestUsGestureRemote destID))
"Neither local not remote"
"Both local and remote"
Right themID -> (,False) <$>
requireEitherAlt
(fmap destThemGestureLocalAdd <$> getValBy (UniqueDestThemGestureLocal themID))
(fmap (destThemGestureRemoteActor &&& destThemGestureRemoteAdd) <$> getValBy (UniqueDestThemGestureRemote themID))
"Neither local not remote"
"Both local and remote"
(,us) <$> case addOrActor of
Left addID -> do
OutboxItem outboxID _ time <- getJust addID
Entity actorID actor <- getByJust $ UniqueActorOutbox outboxID
(,time) . Left . (,actor) <$> getLocalActor actorID
Right (actorID, addID) -> do
RemoteActivity _ _ time <- getJust addID
(,time) . Right <$> getRemoteActorData actorID
return (inviter, us, child, accept, time, role, destID)
$(widgetFile "group/children") $(widgetFile "group/children")
where
getRemoteActorData actorID = do
actor <- getJust actorID
object <- getJust $ remoteActorIdent actor
inztance <- getJust $ remoteObjectInstance object
return (inztance, object, actor)
getGroupChildLiveR :: KeyHashid Group -> KeyHashid DestUsStart -> Handler () getGroupChildLiveR :: KeyHashid Group -> KeyHashid DestUsStart -> Handler ()
getGroupChildLiveR groupHash startHash = do getGroupChildLiveR groupHash startHash = do
@ -531,7 +603,7 @@ getGroupParentsR groupHash = do
encodeRouteHome $ GroupR $ hashGroup parentID encodeRouteHome $ GroupR $ hashGroup parentID
makeId (Right (i, ro, _)) = makeId (Right (i, ro, _)) =
ObjURI (instanceHost i) (remoteObjectIdent ro) ObjURI (instanceHost i) (remoteObjectIdent ro)
makeItem (role, time, i) = AP.Relationship makeItem (role, time, i, _) = AP.Relationship
{ AP.relationshipId = Nothing { AP.relationshipId = Nothing
, AP.relationshipExtraTypes = [] , AP.relationshipExtraTypes = []
, AP.relationshipSubject = encodeRouteHome $ GroupR groupHash , AP.relationshipSubject = encodeRouteHome $ GroupR groupHash
@ -558,13 +630,13 @@ getGroupParentsR groupHash = do
where where
getParents groupID = fmap (sortOn $ view _2) $ liftA2 (++) getParents groupID = fmap (sortOn $ view _2) $ liftA2 (++)
(map (\ (E.Value role, E.Value time, E.Value parent, Entity _ actor) -> (map (\ (E.Value role, E.Value time, E.Value parent, Entity _ actor, E.Value sourceID) ->
(role, time, Left (parent, actor)) (role, time, Left (parent, actor), sourceID)
) )
<$> getLocals groupID <$> getLocals groupID
) )
(map (\ (E.Value role, E.Value time, Entity _ i, Entity _ ro, Entity _ ra) -> (map (\ (E.Value role, E.Value time, Entity _ i, Entity _ ro, Entity _ ra, E.Value sourceID) ->
(role, time, Right (i, ro, ra)) (role, time, Right (i, ro, ra), sourceID)
) )
<$> getRemotes groupID <$> getRemotes groupID
) )
@ -584,6 +656,7 @@ getGroupParentsR groupHash = do
, grant E.^. OutboxItemPublished , grant E.^. OutboxItemPublished
, topic E.^. SourceTopicGroupParent , topic E.^. SourceTopicGroupParent
, actor , actor
, source E.^. SourceId
) )
getRemotes groupID = getRemotes groupID =
@ -603,10 +676,80 @@ getGroupParentsR groupHash = do
, i , i
, ro , ro
, ra , ra
, source E.^. SourceId
) )
getHtml groupID group actor parents = do getHtml groupID group actor parents = do
mp <- maybeAuthId
haveAdmin <- fmap isJust $ handlerToWidget $ runDB $ runMaybeT $ do
personID <- MaybeT $ pure mp
MaybeT $ getCapability personID (Left $ groupResource group) AP.RoleAdmin
((_, widgetAC), enctypeAC) <- runFormPost addParentForm
invites <- handlerToWidget $ runDB $ do
sources <- E.select $ E.from $ \ (source `E.InnerJoin` holder `E.LeftOuterJoin` deleg) -> do
E.on $ E.just (source E.^. SourceId) E.==. deleg E.?. SourceUsSendDelegatorSource
E.on $ source E.^. SourceId E.==. holder E.^. SourceHolderGroupSource
E.where_ $
holder E.^. SourceHolderGroupGroup E.==. E.val groupID E.&&.
E.isNothing (deleg E.?. SourceUsSendDelegatorId)
E.orderBy [E.asc $ source E.^. SourceId]
return source
for sources $ \ (Entity sourceID (Source role)) -> do
(parent, accept) <- do
topic <- getSourceTopic sourceID
accept <-
case bimap fst fst topic of
Left localID -> isJust <$> getBy (UniqueSourceThemAcceptLocal localID)
Right remoteID -> isJust <$> getBy (UniqueSourceThemAcceptRemote remoteID)
(,accept) <$> bitraverse
(\ (_, e) -> do
jID <-
case e of
Right j -> pure j
Left _ -> error "I'm a Group but my parent is a Project"
j <- getJust jID
actor <- getJust $ groupActor j
return (jID, actor)
)
(\ (_, actorID) -> getRemoteActorData actorID)
topic
((inviter, time), us) <- do
usOrThem <-
requireEitherAlt
(getKeyBy $ UniqueSourceOriginUs sourceID)
(getKeyBy $ UniqueSourceOriginThem sourceID)
"Neither us nor them"
"Both us and them"
(addOrActor, us) <-
case usOrThem of
Left usID -> (,True) <$>
requireEitherAlt
(fmap sourceUsGestureLocalAdd <$> getValBy (UniqueSourceUsGestureLocal usID))
(fmap (sourceUsGestureRemoteActor &&& sourceUsGestureRemoteAdd) <$> getValBy (UniqueSourceUsGestureRemote usID))
"Neither local not remote"
"Both local and remote"
Right themID -> (,False) <$>
requireEitherAlt
(fmap sourceThemGestureLocalAdd <$> getValBy (UniqueSourceThemGestureLocal themID))
(fmap (sourceThemGestureRemoteActor &&& sourceThemGestureRemoteAdd) <$> getValBy (UniqueSourceThemGestureRemote themID))
"Neither local not remote"
"Both local and remote"
(,us) <$> case addOrActor of
Left addID -> do
OutboxItem outboxID _ time <- getJust addID
Entity actorID actor <- getByJust $ UniqueActorOutbox outboxID
(,time) . Left . (,actor) <$> getLocalActor actorID
Right (actorID, addID) -> do
RemoteActivity _ _ time <- getJust addID
(,time) . Right <$> getRemoteActorData actorID
return (inviter, us, parent, accept, time, role, sourceID)
$(widgetFile "group/parents") $(widgetFile "group/parents")
where
getRemoteActorData actorID = do
actor <- getJust actorID
object <- getJust $ remoteActorIdent actor
inztance <- getJust $ remoteObjectInstance object
return (inztance, object, actor)
getGroupMemberLiveR getGroupMemberLiveR
:: KeyHashid Group -> KeyHashid CollabEnable -> Handler () :: KeyHashid Group -> KeyHashid CollabEnable -> Handler ()

View file

@ -1,6 +1,7 @@
$# This file is part of Vervis. $# This file is part of Vervis.
$# $#
$# Written in 2016, 2019, 2022, 2023 by fr33domlover <fr33domlover@riseup.net>. $# Written in 2016, 2019, 2022, 2023, 2024
$# 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.
$# $#
@ -21,8 +22,49 @@ $# <http://creativecommons.org/publicdomain/zero/1.0/>.
<th>Role <th>Role
<th>Since <th>Since
<th>Child <th>Child
$forall (role, since, child) <- children $if haveAdmin
<th>Remove
$forall (role, since, child, destID) <- children
<tr> <tr>
<td>#{show role} <td>#{show role}
<td>#{showDate since} <td>#{showDate since}
<td>^{groupLinkFedW child} <td>^{groupLinkFedW child}
$if haveAdmin
<td>^{buttonW POST "Remove" (GroupRemoveChildR groupHash destID)}
$if haveAdmin
<p>Add a child:
<form method=POST action=@{GroupAddChildR groupHash} enctype=#{enctypeAP}>
^{widgetAP}
<input type=submit>
<h2>Invites
<table>
<tr>
<th>Inviter
<th>Via
<th>Invited child
<th>I accepted?
<th>Role
<th>Time
$if haveAdmin
<th>Approve
$forall (inviter, us, child, accept, time, role, destID) <- invites
<tr>
<td>^{actorLinkFedW inviter}
<td>
$if us
Us
$else
Them
<td>^{groupLinkFedW child}
<td>
$if accept
[x]
$else
[_]
<td>#{show role}
<td>#{showDate time}
$if haveAdmin && (not accept && not us)
<td>^{buttonW POST "Approve" (GroupApproveChildR groupHash destID)}

View file

@ -1,6 +1,7 @@
$# This file is part of Vervis. $# This file is part of Vervis.
$# $#
$# Written in 2016, 2019, 2022, 2023 by fr33domlover <fr33domlover@riseup.net>. $# Written in 2016, 2019, 2022, 2023, 2024
$# 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,9 +21,50 @@ $# <http://creativecommons.org/publicdomain/zero/1.0/>.
<tr> <tr>
<th>Role <th>Role
<th>Since <th>Since
<th>Child <th>Parent
$forall (role, since, parent) <- parents $if haveAdmin
<th>Remove
$forall (role, since, parent, sourceID) <- parents
<tr> <tr>
<td>#{show role} <td>#{show role}
<td>#{showDate since} <td>#{showDate since}
<td>^{groupLinkFedW parent} <td>^{groupLinkFedW parent}
$if haveAdmin
<td>^{buttonW POST "Remove" (GroupRemoveParentR groupHash sourceID)}
$if haveAdmin
<p>Add a parent:
<form method=POST action=@{GroupAddParentR groupHash} enctype=#{enctypeAC}>
^{widgetAC}
<input type=submit>
<h2>Invites
<table>
<tr>
<th>Inviter
<th>Via
<th>Invited parent
<th>Parent accepted?
<th>Role
<th>Time
$if haveAdmin
<th>Approve
$forall (inviter, us, parent, accept, time, role, sourceID) <- invites
<tr>
<td>^{actorLinkFedW inviter}
<td>
$if us
Us
$else
Them
<td>^{groupLinkFedW parent}
<td>
$if accept
[x]
$else
[_]
<td>#{show role}
<td>#{showDate time}
$if haveAdmin && (accept && not us)
<td>^{buttonW POST "Approve" (GroupApproveParentR groupHash sourceID)}