1
0
Fork 0
mirror of https://code.sup39.dev/repos/Wqawg synced 2024-12-27 19:24:52 +09:00

UI & Vocab: Project components list & link from collabs JSON to project

This commit is contained in:
Pere Lev 2023-06-27 21:07:21 +03:00
parent 6ae079a310
commit 1fd46b0590
No known key found for this signature in database
GPG key ID: 5252C5C863E5E57D
18 changed files with 136 additions and 33 deletions

View file

@ -227,6 +227,7 @@ provideEmptyCollection typ here = do
, AP.collectionFirst = Nothing , AP.collectionFirst = Nothing
, AP.collectionLast = Nothing , AP.collectionLast = Nothing
, AP.collectionItems = [] :: [Text] , AP.collectionItems = [] :: [Text]
, AP.collectionContext = Nothing
} }
provideHtmlAndAP coll $ redirectToPrettyJSON here provideHtmlAndAP coll $ redirectToPrettyJSON here

View file

@ -120,8 +120,9 @@ projectAdd now projectID (Verse authorIdMsig body) add = do
-- Check input -- Check input
component <- do component <- do
let author = bimap (view _1) (remoteAuthorURI . view _1) authorIdMsig let author = bimap (view _1) (remoteAuthorURI . view _1) authorIdMsig
(component, project) <- parseAdd author add (component, projectComps) <- parseAdd author add
unless (project == Left projectID) $ throwE "Add target isn't me" unless (projectComps == Left projectID) $
throwE "Add target isn't my components collection"
return component return component
-- If component is local, find it in our DB -- If component is local, find it in our DB

View file

@ -47,6 +47,7 @@ module Vervis.Data.Collab
, grantResourceLocalActor , grantResourceLocalActor
, ComponentBy (..) , ComponentBy (..)
, componentActor
) )
where where
@ -281,21 +282,20 @@ parseAdd
, Either ProjectId FedURI , Either ProjectId FedURI
) )
parseAdd sender (AP.Add object target) = do parseAdd sender (AP.Add object target) = do
result@(component, project) <- result@(component, collection) <-
(,) <$> nameExceptT "Add.object" (parseComponent' object) (,) <$> nameExceptT "Add.object" (parseComponent' object)
<*> nameExceptT "Add.target" (parseProject target) <*> nameExceptT "Add.target" (parseProjectComps target)
case result of case result of
(Right u, Right v) | u == v -> throwE "Object and target are the same" (Right u, Right v) | u == v -> throwE "Object and target are the same"
_ -> pure () _ -> pure ()
when (sender == first componentActor component) $ when (sender == first componentActor component) $
throwE "Sender and component are the same" throwE "Sender and component are the same"
when (sender == first LocalActorProject project) $ case collection of
throwE "Sender and project are the same" Left projectID | sender == Left (LocalActorProject projectID) ->
throwE "Sender and project are the same"
_ -> pure ()
return result return result
where where
componentActor (ComponentRepo r) = LocalActorRepo r
componentActor (ComponentDeck d) = LocalActorDeck d
componentActor (ComponentLoom l) = LocalActorLoom l
parseComponent' (Right _) = throwE "Not a component URI" parseComponent' (Right _) = throwE "Not a component URI"
parseComponent' (Left u) = do parseComponent' (Left u) = do
routeOrRemote <- parseFedURI u routeOrRemote <- parseFedURI u
@ -316,12 +316,12 @@ parseAdd sender (AP.Add object target) = do
parseComponent (DeckR d) = Just $ ComponentDeck d parseComponent (DeckR d) = Just $ ComponentDeck d
parseComponent (LoomR l) = Just $ ComponentLoom l parseComponent (LoomR l) = Just $ ComponentLoom l
parseComponent _ = Nothing parseComponent _ = Nothing
parseProject u = do parseProjectComps u = do
routeOrRemote <- parseFedURI u routeOrRemote <- parseFedURI u
bitraverse bitraverse
(\case (\case
ProjectR j -> WAP.decodeKeyHashidE j "Inavlid hashid" ProjectComponentsR j -> WAP.decodeKeyHashidE j "Inavlid hashid"
_ -> throwE "Not a project route" _ -> throwE "Not a project components collection route"
) )
pure pure
routeOrRemote routeOrRemote
@ -434,3 +434,7 @@ unhashComponent c = do
return $ unhashComponentPure ctx c return $ unhashComponentPure ctx c
unhashComponentE c e = ExceptT $ maybe (Left e) Right <$> unhashComponent c unhashComponentE c e = ExceptT $ maybe (Left e) Right <$> unhashComponent c
componentActor (ComponentRepo r) = LocalActorRepo r
componentActor (ComponentDeck d) = LocalActorDeck d
componentActor (ComponentLoom l) = LocalActorLoom l

View file

@ -1000,3 +1000,5 @@ instance YesodBreadcrumbs App where
ProjectInviteR d -> ("Invite", Just $ ProjectR d) ProjectInviteR d -> ("Invite", Just $ ProjectR d)
ProjectRemoveR _ _ -> ("", Nothing) ProjectRemoveR _ _ -> ("", Nothing)
ProjectComponentsR j -> ("Components", Just $ ProjectR j)

View file

@ -1123,6 +1123,7 @@ getRepoProposalsR shr rp = do
, collectionFirst = Just $ pageUrl 1 , collectionFirst = Just $ pageUrl 1
, collectionLast = Just $ pageUrl pages , collectionLast = Just $ pageUrl pages
, collectionItems = [] :: [Text] , collectionItems = [] :: [Text]
, collectionContext = Nothing
} }
Just (patches, navModel) -> Just (patches, navModel) ->
let current = nmCurrent navModel let current = nmCurrent navModel

View file

@ -285,6 +285,7 @@ getDeckTicketsR deckHash = selectRep $ do
, collectionFirst = Just $ pageUrl 1 , collectionFirst = Just $ pageUrl 1
, collectionLast = Just $ pageUrl pages , collectionLast = Just $ pageUrl pages
, collectionItems = [] :: [Text] , collectionItems = [] :: [Text]
, collectionContext = Nothing
} }
Just (tickets, navModel) -> Just (tickets, navModel) ->
let current = nmCurrent navModel let current = nmCurrent navModel
@ -707,6 +708,7 @@ getProjectTeamR shr prj = do
, collectionFirst = Nothing , collectionFirst = Nothing
, collectionLast = Nothing , collectionLast = Nothing
, collectionItems = map (encodeRouteHome . SharerR) memberShrs , collectionItems = map (encodeRouteHome . SharerR) memberShrs
, collectionContext = Nothing
} }
provideHtmlAndAP team $ redirect (here, [("prettyjson", "true")]) provideHtmlAndAP team $ redirect (here, [("prettyjson", "true")])
-} -}

View file

@ -236,6 +236,7 @@ getLoomClothsR loomHash = selectRep $ do
, AP.collectionFirst = Just $ pageUrl 1 , AP.collectionFirst = Just $ pageUrl 1
, AP.collectionLast = Just $ pageUrl pages , AP.collectionLast = Just $ pageUrl pages
, AP.collectionItems = [] :: [Text] , AP.collectionItems = [] :: [Text]
, AP.collectionContext = Nothing
} }
Just (tickets, navModel) -> Just (tickets, navModel) ->
let current = nmCurrent navModel let current = nmCurrent navModel

View file

@ -32,6 +32,8 @@ module Vervis.Handler.Project
, getProjectInviteR , getProjectInviteR
, postProjectInviteR , postProjectInviteR
, postProjectRemoveR , postProjectRemoveR
, getProjectComponentsR
) )
where where
@ -40,6 +42,7 @@ import Control.Monad
import Control.Monad.Trans.Except import Control.Monad.Trans.Except
import Control.Monad.Trans.Maybe import Control.Monad.Trans.Maybe
import Data.Aeson import Data.Aeson
import Data.Bifunctor
import Data.Bitraversable import Data.Bitraversable
import Data.ByteString (ByteString) import Data.ByteString (ByteString)
import Data.Default.Class import Data.Default.Class
@ -81,6 +84,7 @@ import Yesod.Persist.Local
import Vervis.Access import Vervis.Access
import Vervis.API import Vervis.API
import Vervis.Data.Collab
import Vervis.Federation.Auth import Vervis.Federation.Auth
import Vervis.Federation.Collab import Vervis.Federation.Collab
import Vervis.Federation.Discussion import Vervis.Federation.Discussion
@ -147,7 +151,10 @@ getProjectR projectHash = do
, AP.projectTracker = Nothing , AP.projectTracker = Nothing
, AP.projectChildren = [] , AP.projectChildren = []
, AP.projectParents = [] , AP.projectParents = []
, AP.projectComponents = [] , AP.projectComponents =
encodeRouteLocal $ ProjectComponentsR projectHash
, AP.projectCollaborators =
encodeRouteLocal $ ProjectCollabsR projectHash
} }
provideHtmlAndAP projectAP $(widgetFile "project/one") provideHtmlAndAP projectAP $(widgetFile "project/one")
where where
@ -330,3 +337,79 @@ postProjectRemoveR projectHash ctID = do
Right removeID -> Right removeID ->
setMessage "Remove sent" setMessage "Remove sent"
redirect $ ProjectCollabsR projectHash redirect $ ProjectCollabsR projectHash
getProjectComponentsR :: KeyHashid Project -> Handler TypedContent
getProjectComponentsR projectHash = do
projectID <- decodeKeyHashid404 projectHash
components <- runDB $ concat <$> sequence
[ map (Left . ComponentRepo) <$> getRepos projectID
, map (Left . ComponentDeck) <$> getDecks projectID
, map (Left . ComponentLoom) <$> getLooms projectID
, map Right <$> getRemotes projectID
]
encodeRouteLocal <- getEncodeRouteLocal
encodeRouteHome <- getEncodeRouteHome
hashActor <- getHashLocalActor
let componentsAP = Collection
{ collectionId = encodeRouteLocal here
, collectionType = CollectionTypeUnordered
, collectionTotalItems = Just $ length components
, collectionCurrent = Nothing
, collectionFirst = Nothing
, collectionLast = Nothing
, collectionItems =
map (bimap
( encodeRouteHome
. renderLocalActor
. hashActor
. componentActor
)
id
)
components
, collectionContext =
Just $ encodeRouteLocal $ ProjectR projectHash
}
provideHtmlAndAP componentsAP $ redirectToPrettyJSON here
where
here = ProjectComponentsR projectHash
getRepos projectID =
fmap (map E.unValue) $
E.select $ E.from $ \ (comp `E.InnerJoin` enable `E.InnerJoin` local `E.InnerJoin` repo) -> do
E.on $ local E.^. ComponentLocalId E.==. repo E.^. ComponentLocalRepoComponent
E.on $ comp E.^. ComponentId E.==. local E.^. ComponentLocalComponent
E.on $ comp E.^. ComponentId E.==. enable E.^. ComponentEnableComponent
E.where_ $ comp E.^. ComponentProject E.==. E.val projectID
return $ repo E.^. ComponentLocalRepoRepo
getDecks projectID =
fmap (map E.unValue) $
E.select $ E.from $ \ (comp `E.InnerJoin` enable `E.InnerJoin` local `E.InnerJoin` deck) -> do
E.on $ local E.^. ComponentLocalId E.==. deck E.^. ComponentLocalDeckComponent
E.on $ comp E.^. ComponentId E.==. local E.^. ComponentLocalComponent
E.on $ comp E.^. ComponentId E.==. enable E.^. ComponentEnableComponent
E.where_ $ comp E.^. ComponentProject E.==. E.val projectID
return $ deck E.^. ComponentLocalDeckDeck
getLooms projectID =
fmap (map E.unValue) $
E.select $ E.from $ \ (comp `E.InnerJoin` enable `E.InnerJoin` local `E.InnerJoin` loom) -> do
E.on $ local E.^. ComponentLocalId E.==. loom E.^. ComponentLocalLoomComponent
E.on $ comp E.^. ComponentId E.==. local E.^. ComponentLocalComponent
E.on $ comp E.^. ComponentId E.==. enable E.^. ComponentEnableComponent
E.where_ $ comp E.^. ComponentProject E.==. E.val projectID
return $ loom E.^. ComponentLocalLoomLoom
getRemotes projectID =
fmap (map $ uncurry ObjURI . bimap E.unValue E.unValue) $
E.select $ E.from $ \ (comp `E.InnerJoin` enable `E.InnerJoin` remote `E.InnerJoin` ra `E.InnerJoin` ro `E.InnerJoin` i) -> do
E.on $ ro E.^. RemoteObjectInstance E.==. i E.^. InstanceId
E.on $ ra E.^. RemoteActorIdent E.==. ro E.^. RemoteObjectId
E.on $ remote E.^. ComponentRemoteActor E.==. ra E.^. RemoteActorId
E.on $ comp E.^. ComponentId E.==. remote E.^. ComponentRemoteComponent
E.on $ comp E.^. ComponentId E.==. enable E.^. ComponentEnableComponent
E.where_ $ comp E.^. ComponentProject E.==. E.val projectID
return (i E.^. InstanceHost, ro E.^. RemoteObjectIdent)

View file

@ -981,6 +981,7 @@ getRepoTeamR shr rp = do
, collectionFirst = Nothing , collectionFirst = Nothing
, collectionLast = Nothing , collectionLast = Nothing
, collectionItems = map (encodeRouteHome . SharerR) memberShrs , collectionItems = map (encodeRouteHome . SharerR) memberShrs
, collectionContext = Nothing
} }
provideHtmlAndAP team $ redirectToPrettyJSON here provideHtmlAndAP team $ redirectToPrettyJSON here

View file

@ -936,6 +936,7 @@ getProjectTicketTeamR shr prj ltkhid = do
, collectionFirst = Nothing , collectionFirst = Nothing
, collectionLast = Nothing , collectionLast = Nothing
, collectionItems = map (encodeRouteHome . SharerR) memberShrs , collectionItems = map (encodeRouteHome . SharerR) memberShrs
, collectionContext = Nothing
} }
provideHtmlAndAP team $ redirectToPrettyJSON here provideHtmlAndAP team $ redirectToPrettyJSON here

View file

@ -648,6 +648,7 @@ getDependencyCollection here depRoute getLocalTicketId404 = do
, collectionLast = Nothing , collectionLast = Nothing
, collectionItems = , collectionItems =
map (encodeRouteHome . depRoute . encodeHid) tdids map (encodeRouteHome . depRoute . encodeHid) tdids
, collectionContext = Nothing
} }
provideHtmlAndAP deps $ redirectToPrettyJSON here provideHtmlAndAP deps $ redirectToPrettyJSON here
@ -670,6 +671,7 @@ getReverseDependencyCollection here getLocalTicketId404 = do
, collectionItems = , collectionItems =
map (encodeRouteHome . TicketDepR . encodeHid) locals ++ map (encodeRouteHome . TicketDepR . encodeHid) locals ++
map (\ (E.Value h, E.Value lu) -> ObjURI h lu) remotes map (\ (E.Value h, E.Value lu) -> ObjURI h lu) remotes
, collectionContext = Nothing
} }
provideHtmlAndAP deps $ redirectToPrettyJSON here provideHtmlAndAP deps $ redirectToPrettyJSON here
where where

View file

@ -158,6 +158,7 @@ getInbox here actor hash = do
, collectionFirst = Just $ pageUrl 1 , collectionFirst = Just $ pageUrl 1
, collectionLast = Just $ pageUrl pages , collectionLast = Just $ pageUrl pages
, collectionItems = [] :: [Text] , collectionItems = [] :: [Text]
, collectionContext = Nothing
} }
provideRep (redirectFirstPage here' :: Handler Html) provideRep (redirectFirstPage here' :: Handler Html)
Just (items, navModel) -> do Just (items, navModel) -> do
@ -321,6 +322,7 @@ getOutbox here itemRoute grabActorID hash = do
, collectionFirst = Just $ pageUrl 1 , collectionFirst = Just $ pageUrl 1
, collectionLast = Just $ pageUrl pages , collectionLast = Just $ pageUrl pages
, collectionItems = [] :: [Text] , collectionItems = [] :: [Text]
, collectionContext = Nothing
} }
provideRep (redirectFirstPage here' :: Handler Html) provideRep (redirectFirstPage here' :: Handler Html)
Just (items, navModel) -> do Just (items, navModel) -> do
@ -424,6 +426,7 @@ getFollowersCollection here getFsid = do
, collectionItems = , collectionItems =
map (encodeRouteHome . renderLocalActor . hashActor) locals ++ map (encodeRouteHome . renderLocalActor . hashActor) locals ++
map (uncurry ObjURI . bimap E.unValue E.unValue) remotes map (uncurry ObjURI . bimap E.unValue E.unValue) remotes
, collectionContext = Nothing
} }
provideHtmlAndAP followersAP $ redirectToPrettyJSON here provideHtmlAndAP followersAP $ redirectToPrettyJSON here
@ -468,6 +471,7 @@ getFollowingCollection here actor hash = do
, collectionFirst = Nothing , collectionFirst = Nothing
, collectionLast = Nothing , collectionLast = Nothing
, collectionItems = map encodeRouteHome locals ++ remotes , collectionItems = map encodeRouteHome locals ++ remotes
, collectionContext = Nothing
} }
provideHtmlAndAP followingAP $ redirectToPrettyJSON here' provideHtmlAndAP followingAP $ redirectToPrettyJSON here'
where where

View file

@ -133,6 +133,7 @@ getDarcsRepoChanges repo = do
, AP.collectionFirst = Just $ pageUrl 1 , AP.collectionFirst = Just $ pageUrl 1
, AP.collectionLast = Just $ pageUrl pages , AP.collectionLast = Just $ pageUrl pages
, AP.collectionItems = [] :: [Text] , AP.collectionItems = [] :: [Text]
, AP.collectionContext = Nothing
} }
provideHtmlAndAP collection $ redirectFirstPage here provideHtmlAndAP collection $ redirectFirstPage here
Just (_total, pages, items, navModel) -> Just (_total, pages, items, navModel) ->

View file

@ -100,6 +100,7 @@ getRepliesCollection here getDiscussionId404 = do
, AP.collectionLast = Nothing , AP.collectionLast = Nothing
, AP.collectionItems = , AP.collectionItems =
map localUri locals ++ map remoteUri remotes map localUri locals ++ map remoteUri remotes
, AP.collectionContext = Nothing
} }
where where
selectLocals did = do selectLocals did = do

View file

@ -165,6 +165,7 @@ getGitRepoChanges repo ref = do
, AP.collectionFirst = Just $ pageUrl 1 , AP.collectionFirst = Just $ pageUrl 1
, AP.collectionLast = Just $ pageUrl pages , AP.collectionLast = Just $ pageUrl pages
, AP.collectionItems = [] :: [Text] , AP.collectionItems = [] :: [Text]
, AP.collectionContext = Nothing
} }
provideHtmlAndAP collection $ redirectFirstPage here provideHtmlAndAP collection $ redirectFirstPage here
Just (_total, pages, items, navModel) -> Just (_total, pages, items, navModel) ->

View file

@ -702,6 +702,7 @@ data Collection a u = Collection
, collectionFirst :: Maybe LocalPageURI , collectionFirst :: Maybe LocalPageURI
, collectionLast :: Maybe LocalPageURI , collectionLast :: Maybe LocalPageURI
, collectionItems :: [a] , collectionItems :: [a]
, collectionContext :: Maybe LocalURI
} }
instance (FromJSON a, ToJSON a) => ActivityPub (Collection a) where instance (FromJSON a, ToJSON a) => ActivityPub (Collection a) where
@ -716,7 +717,8 @@ instance (FromJSON a, ToJSON a) => ActivityPub (Collection a) where
<*> withAuthorityMaybeP authority (o .:? "first") <*> withAuthorityMaybeP authority (o .:? "first")
<*> withAuthorityMaybeP authority (o .:? "last") <*> withAuthorityMaybeP authority (o .:? "last")
<*> optional (o .: "items" <|> o .: "orderedItems") .!= [] <*> optional (o .: "items" <|> o .: "orderedItems") .!= []
toSeries authority (Collection id_ typ total curr firzt last items) <*> withAuthorityMaybeO authority (o .:? "context")
toSeries authority (Collection id_ typ total curr firzt last items ctx)
= "id" .= ObjURI authority id_ = "id" .= ObjURI authority id_
<> "type" .= typ <> "type" .= typ
<> "totalItems" .=? total <> "totalItems" .=? total
@ -724,6 +726,7 @@ instance (FromJSON a, ToJSON a) => ActivityPub (Collection a) where
<> "first" .=? (PageURI authority <$> firzt) <> "first" .=? (PageURI authority <$> firzt)
<> "last" .=? (PageURI authority <$> last) <> "last" .=? (PageURI authority <$> last)
<> itemsProp .=% items <> itemsProp .=% items
<> "context" .=? (ObjURI authority <$> ctx)
where where
itemsProp = itemsProp =
case typ of case typ of
@ -824,7 +827,8 @@ data Project u = Project
, projectTracker :: Maybe (ObjURI u) , projectTracker :: Maybe (ObjURI u)
, projectChildren :: [ObjURI u] , projectChildren :: [ObjURI u]
, projectParents :: [ObjURI u] , projectParents :: [ObjURI u]
, projectComponents :: [ObjURI u] , projectComponents :: LocalURI
, projectCollaborators :: LocalURI
} }
instance ActivityPub Project where instance ActivityPub Project where
@ -848,18 +852,9 @@ instance ActivityPub Project where
return items return items
) )
<*> o .:? "context" .!= [] <*> o .:? "context" .!= []
<*> (do c <- o .: "components" <*> withAuthorityO h (o .: "components")
typ <- c .: "type" <*> withAuthorityO h (o .: "collaborators")
unless (typ == ("Collection" :: Text)) $ toSeries h (Project actor tracker children parents components collabs)
fail "components.type isn't Collection"
items <- c .: "items"
mtotal <- c .:? "totalItems"
for_ mtotal $ \ total ->
unless (length items == total) $
fail "Incorrect totalItems"
return items
)
toSeries h (Project actor tracker children parents components)
= toSeries h actor = toSeries h actor
<> "ticketsTrackedBy" .=? tracker <> "ticketsTrackedBy" .=? tracker
<> "subprojects" `pair` pairs <> "subprojects" `pair` pairs
@ -867,12 +862,9 @@ instance ActivityPub Project where
<> "items" .= children <> "items" .= children
<> "totalItems" .= length children <> "totalItems" .= length children
) )
<> "context" .= parents <> "context" .= parents
<> "components" `pair` pairs <> "components" .= ObjURI h components
( "type" .= ("Collection" :: Text) <> "collaborators" .= ObjURI h collabs
<> "items" .= components
<> "totalItems" .= length components
)
data Audience u = Audience data Audience u = Audience
{ audienceTo :: [ObjURI u] { audienceTo :: [ObjURI u]

View file

@ -30,6 +30,9 @@ $# <http://creativecommons.org/publicdomain/zero/1.0/>.
<span> <span>
<a href=@{ProjectCollabsR projectHash}> <a href=@{ProjectCollabsR projectHash}>
[🤝 Collaborators] [🤝 Collaborators]
<span>
<a href=@{ProjectComponentsR projectHash}>
[🧩 Components]
<span> <span>
[No wiki] [No wiki]
<span> <span>

View file

@ -322,3 +322,5 @@
/projects/#ProjectKeyHashid/collabs ProjectCollabsR GET /projects/#ProjectKeyHashid/collabs ProjectCollabsR GET
/projects/#ProjectKeyHashid/invite ProjectInviteR GET POST /projects/#ProjectKeyHashid/invite ProjectInviteR GET POST
/projects/#ProjectKeyHashid/remove/#CollabTopicProjectId ProjectRemoveR POST /projects/#ProjectKeyHashid/remove/#CollabTopicProjectId ProjectRemoveR POST
/projects/#ProjectKeyHashid/components ProjectComponentsR GET