@prefix this: . @prefix sub: . @prefix np: . @prefix grlc: . @prefix dct: . @prefix nt: . @prefix npx: . @prefix xsd: . @prefix rdfs: . @prefix orcid: . @prefix prov: . @prefix foaf: . sub:Head { this: a np:Nanopublication; np:hasAssertion sub:assertion; np:hasProvenance sub:provenance; np:hasPublicationInfo sub:pubinfo . } sub:assertion { sub:get-nanosuggestions a grlc:grlc-query; dct:description "Returns the nanosuggestions (issues, bug reports, feature requests and tasks) linked to a given space or maintained resource via gen:isRelevantFor, with kind, current status, current assignee, comment count, reporter and date. Anybody may link a nanosuggestion to a resource, but status and assignment are resolved per space: the most recent assertion by a current member (admin, maintainer or member, not observer) of that space wins; if no member has ever set a status, the most recent one from outside is shown and marked as such; with no status at all the nanosuggestion counts as open. Also returns the assignment nanopublication that currently wins, so that an assign action can open it in override mode and arrive pre-filled with the current assignees."; dct:license ; rdfs:label "Get nanosuggestions for a resource"; grlc:endpoint ; grlc:sparql """ prefix rdf: prefix rdfs: prefix dct: prefix foaf: prefix np: prefix npa: prefix npx: prefix schema: prefix as: prefix gen: prefix nsug: select ?item_multi_iri ?item_label_multi ?kind ?status ?assignee ?assignee_label ?comments_multi_iri ?comments_label_multi ?reporter ?reporter_label ?date ?suggestion ?np ?override_target where { graph npa:graph { ?np npa:hasValidSignatureForPublicKeyHash ?pubkey . filter not exists { ?npi npx:invalidates ?np ; npa:hasValidSignatureForPublicKeyHash ?pubkey . } ?np dct:created ?date . ?np np:hasAssertion ?a . optional { ?np dct:creator ?reporter } } graph ?a { ?suggestion a nsug:Nanosuggestion ; rdfs:label ?title . optional { ?suggestion a ?k . filter(?k != nsug:Nanosuggestion && ?k != schema:Statement) } } filter exists { graph npa:graph { ?lnp npa:hasValidSignatureForPublicKeyHash ?lpk ; np:hasAssertion ?la . filter not exists { ?lnpi npx:invalidates ?lnp ; npa:hasValidSignatureForPublicKeyHash ?lpk . } } graph ?la { values ?_resource_multi_iri {} ?suggestion gen:isRelevantFor ?_resource_multi_iri . } } optional { { select ?suggestion (max(concat(if(?fm,'1','0'), ?sd, ' ', str(?s))) as ?pick) where { service { select (group_concat(?mpk; separator=' ') as ?memberPubkeys) where { graph npa:graph { npa:thisRepo npa:hasCurrentSpaceState ?stateG . } values ?_resource_multi_iri {} graph ?stateG { ?_resource_multi_iri npa:isMaintainedBy? ?space . ?ri a gen:RoleInstantiation ; npa:forSpace ?space ; npa:forAgent ?agent ; npa:hasRoleType ?rt . filter(?rt in (gen:AdminRole, gen:MaintainerRole, gen:MemberRole)) ?acct a npa:AccountState ; npa:agent ?agent ; npa:pubkey ?mpk . } } } graph npa:graph { ?snp npa:hasValidSignatureForPublicKeyHash ?spk ; np:hasAssertion ?sa ; dct:created ?sdate . filter not exists { ?snpi npx:invalidates ?snp ; npa:hasValidSignatureForPublicKeyHash ?spk . } } graph ?sa { ?suggestion schema:actionStatus ?s . } bind(str(?sdate) as ?sd) bind(contains(?memberPubkeys, ?spk) as ?fm) } group by ?suggestion } } bind(coalesce(iri(strafter(?pick, ' ')), schema:PotentialActionStatus) as ?st) bind(coalesce(substr(?pick, 1, 1) = '0', false) as ?outside) bind(if(?st = schema:CompletedActionStatus, 'done', if(?st = schema:FailedActionStatus, 'rejected', if(?st = schema:ActiveActionStatus, 'in progress', 'open'))) as ?st_label) bind(if(?outside, concat(?st_label, ' (set outside this space)'), ?st_label) as ?status) optional { { select ?suggestion (max(concat(if(?afm,'1','0'), ?ad, ' ', str(?ag))) as ?apick) where { service { select (group_concat(?mpk; separator=' ') as ?memberPubkeys) where { graph npa:graph { npa:thisRepo npa:hasCurrentSpaceState ?stateG . } values ?_resource_multi_iri {} graph ?stateG { ?_resource_multi_iri npa:isMaintainedBy? ?space . ?ri a gen:RoleInstantiation ; npa:forSpace ?space ; npa:forAgent ?agent ; npa:hasRoleType ?rt . filter(?rt in (gen:AdminRole, gen:MaintainerRole, gen:MemberRole)) ?acct a npa:AccountState ; npa:agent ?agent ; npa:pubkey ?mpk . } } } graph npa:graph { ?anp npa:hasValidSignatureForPublicKeyHash ?apk ; np:hasAssertion ?aa ; dct:created ?adate . filter not exists { ?anpi npx:invalidates ?anp ; npa:hasValidSignatureForPublicKeyHash ?apk . } } graph ?aa { ?suggestion schema:agent ?ag . } bind(str(?adate) as ?ad) bind(contains(?memberPubkeys, ?apk) as ?afm) } group by ?suggestion } bind(iri(strafter(?apick, ' ')) as ?assignee) } # The assignment nanopub that currently wins, so \"assign...\" can open it in # override mode: the form then arrives pre-filled with ALL current assignees, # whatever their number. Falls back to the declaring nanopub, because a raw-key # (@) mapping with an empty value hides the button entirely. optional { { select ?suggestion (max(concat(if(?nfm,'1','0'), ?nd, ' ', str(?anp2))) as ?npick) where { service { select (group_concat(?mpk; separator=' ') as ?memberPubkeys) where { graph npa:graph { npa:thisRepo npa:hasCurrentSpaceState ?stateG . } values ?_resource_multi_iri {} graph ?stateG { ?_resource_multi_iri npa:isMaintainedBy? ?space . ?ri a gen:RoleInstantiation ; npa:forSpace ?space ; npa:forAgent ?agent ; npa:hasRoleType ?rt . filter(?rt in (gen:AdminRole, gen:MaintainerRole, gen:MemberRole)) ?acct a npa:AccountState ; npa:agent ?agent ; npa:pubkey ?mpk . } } } graph npa:graph { ?anp2 npa:hasValidSignatureForPublicKeyHash ?npk ; np:hasAssertion ?aa2 ; dct:created ?ndate . filter not exists { ?anp2i npx:invalidates ?anp2 ; npa:hasValidSignatureForPublicKeyHash ?npk . } } graph ?aa2 { ?suggestion schema:agent ?ag2 . } bind(str(?ndate) as ?nd) bind(contains(?memberPubkeys, ?npk) as ?nfm) } group by ?suggestion } bind(iri(strafter(?npick, ' ')) as ?assignNp) } bind(coalesce(?assignNp, ?np) as ?override_target) optional { { select ?suggestion (count(distinct ?cnp) as ?ccount) where { graph npa:graph { ?cnp npa:hasValidSignatureForPublicKeyHash ?cpk ; np:hasAssertion ?ca . filter not exists { ?cnpi npx:invalidates ?cnp ; npa:hasValidSignatureForPublicKeyHash ?cpk . } } graph ?ca { ?c a schema:Statement ; rdf:value ?ctext . } ?c as:inReplyTo+ ?suggestion . } group by ?suggestion } filter(?ccount > 0) bind(?suggestion as ?comments_multi_iri) bind(concat(str(?ccount), if(?ccount = 1, ' comment', ' comments')) as ?comments_label_multi) } optional { { select ?reporter (min(?rn) as ?reporter_label) where { ?reporter foaf:name ?rn } group by ?reporter } } optional { { select ?assignee (min(?an) as ?assignee_label) where { ?assignee foaf:name ?an } group by ?assignee } } bind(?suggestion as ?item_multi_iri) bind(?title as ?item_label_multi) bind(coalesce(lcase(strafter(str(?k), 'RA5BAdUvlxLWMWFQN3UVKoIQEB_MYTiAoLH1klXJ7z-XI/')), '') as ?kind) bind(if(?st in (schema:CompletedActionStatus, schema:FailedActionStatus), '2', '1') as ?openRank) } order by ?openRank desc(?date) """ . } sub:provenance { sub:assertion prov:wasAttributedTo orcid:0000-0002-1267-0234 . } sub:pubinfo { orcid:0000-0002-1267-0234 foaf:name "Tobias Kuhn" . this: dct:created "2026-08-27T07:20:40Z"^^xsd:dateTime; dct:creator orcid:0000-0002-1267-0234; dct:license ; npx:embeds sub:get-nanosuggestions; npx:supersedes ; rdfs:label "Get nanosuggestions for a resource"; nt:wasCreatedFromProvenanceTemplate ; nt:wasCreatedFromPubinfoTemplate , , ; nt:wasCreatedFromTemplate . sub:sig npx:hasAlgorithm "RSA"; npx:hasPublicKey "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwUtewGCpT5vIfXYE1bmf/Uqu1ojqnWdYxv+ySO80ul8Gu7m8KoyPAwuvaPj0lvPtHrg000qMmkxzKhYknEjq8v7EerxZNYp5B3/3+5ZpuWOYAs78UnQVjbHSmDdmryr4D4VvvNIiUmd0yxci47dTFUj4DvfHnGd6hVe5+goqdcwIDAQAB"; npx:hasSignature "EzuIeJYan8ZD3xKd9oAq1y/sJkky25tYNWP3CV5K4FrzLXT6P3DAaH7/LyGqQdkycqT3M4Y93UP0LLTZUqCY/kvgmDrGNJew8aYuMVkBqNx0r9fqswBM/hVdlLyKXBeLT0ThwL7P6kgwCc+ILcCGCynWg+vpDwYUte9Junyzzyo="; npx:hasSignatureTarget this:; npx:signedBy orcid:0000-0002-1267-0234 . }