@prefix this: . @prefix sub: . @prefix np: . @prefix grlc: . @prefix dct: . @prefix nt: . @prefix npx: . @prefix xsd: . @prefix skos: . @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:list-maintained-views a grlc:grlc-query; dct:description "Lists the resource views governed by a given space. First the views whose versions declare gen:governedBy the space but which the space does not list as maintained resources yet: they are marked as not listed yet and carry the version-independent IRI, label and description that an admin needs to list them as maintained resources (register_* columns, empty on listed rows). Then the ones listed as maintained resources of the space. Each row shows one name for the view -- the current version's title, or its label where it has no title -- its view type (tabular, list, nanopub set, ...; tabular where none is declared, which is how Nanodash renders it, with '+ query form' for views that show a query form first), and a link to that version's nanopublication. For a listed view the current version is the newest non-invalidated version signed by a current member+ (admin/maintainer/member) of the governing space ref, mirroring the get-latest-governed-version resolver; for one not listed yet it is the newest non-invalidated version signed by a current member+ of the space. The federated lookup for the ones not listed yet gathers the member keys and the listed IRIs into a single row, so it runs once. Views without such a version do not appear. Ordered by status, then alphabetically by name, ignoring a leading emoji."; dct:license ; rdfs:label "List maintained views of a space"; grlc:endpoint ; grlc:sparql """prefix rdfs: prefix dct: prefix np: prefix npa: prefix npx: prefix gen: select ?resource ?resource_label ?type ?status ?register_kind ?register_label ?register_description ?np (\"^\" as ?np_label) where { { select ?resource ?registered ?np ?isForm (coalesce(min(if(lang(?label) = \"\", ?label, ?nolabel)), min(?label)) as ?viewLabel) (coalesce(min(if(lang(?titlex) = \"\", ?titlex, ?notitle)), min(?titlex)) as ?title) (coalesce(min(if(lang(?desc) = \"\", ?desc, ?nodesc)), min(?desc)) as ?description) (min(?typeName) as ?typeVal) where { { select ?resource ?registered (max(concat(str(?gDate), \">\", str(?gNp))) as ?maxW) where { { # Kinds listed as maintained resources of the space: newest version signed by a # current member+ of the governing space ref (as in get-latest-governed-version). values ?_space_multi_iri {} graph npa:graph { ?gNp npa:hasValidSignatureForPublicKeyHash ?gPubkeyhash ; dct:created ?gDate ; npx:embeds ?gVersion ; np:hasAssertion ?gA . filter not exists { ?gInv npx:invalidates ?gNp ; npa:hasValidSignatureForPublicKeyHash ?gPubkeyhash . } } graph ?gA { ?gVersion a gen:ResourceView ; dct:isVersionOf ?resource ; gen:governedBy ?_space_multi_iri . } service { graph npa:graph { npa:thisRepo npa:hasCurrentSpaceState ?stateG . } graph ?stateG { ?resource npa:isMaintainedBy ?_space_multi_iri ; npa:hasGoverningSpaceRef ?gRef . ?gRi a gen:RoleInstantiation ; npa:forSpace ?_space_multi_iri ; npa:forSpaceRef ?gRef ; npa:hasRoleType ?gTier ; npa:forAgent ?gAgent . filter(?gTier = gen:AdminRole || ?gTier = gen:MaintainerRole || ?gTier = gen:MemberRole) ?gAcct a npa:AccountState ; npa:agent ?gAgent ; npa:pubkey ?gPubkeyhash . } } bind(true as ?registered) } union { # Kinds whose versions declare gen:governedBy the space but which the space has not # listed as maintained resources yet: newest version signed by a current member+ of the space. The member keys # and listed kinds are gathered into one row, so the federated call runs once. { select (concat(\" \", group_concat(distinct str(?uKey); separator=\" \"), \" \") as ?uKeys) (concat(\" \", group_concat(distinct str(?uKind); separator=\" \"), \" \") as ?uKinds) where { values ?_space_multi_iri {} service { graph npa:graph { npa:thisRepo npa:hasCurrentSpaceState ?uState . } graph ?uState { ?uRi a gen:RoleInstantiation ; npa:forSpace ?_space_multi_iri ; npa:hasRoleType ?uTier ; npa:forAgent ?uAgent . filter(?uTier = gen:AdminRole || ?uTier = gen:MaintainerRole || ?uTier = gen:MemberRole) ?uAcct a npa:AccountState ; npa:agent ?uAgent ; npa:pubkey ?uKey . } optional { graph ?uState { ?uKind npa:isMaintainedBy ?_space_multi_iri . } } } } } values ?_space_multi_iri {} graph npa:graph { ?gNp npa:hasValidSignatureForPublicKeyHash ?gPubkeyhash ; dct:created ?gDate ; npx:embeds ?gVersion ; np:hasAssertion ?gA . filter not exists { ?gInv npx:invalidates ?gNp ; npa:hasValidSignatureForPublicKeyHash ?gPubkeyhash . } } graph ?gA { ?gVersion a gen:ResourceView ; dct:isVersionOf ?resource ; gen:governedBy ?_space_multi_iri . } filter(contains(?uKeys, concat(\" \", str(?gPubkeyhash), \" \"))) filter(!contains(?uKinds, concat(\" \", str(?resource), \" \"))) bind(false as ?registered) } } group by ?resource ?registered } graph npa:graph { ?np npa:hasValidSignatureForPublicKeyHash ?pubkeyhash ; dct:created ?date ; npx:embeds ?version ; np:hasAssertion ?a . } filter(concat(str(?date), \">\", str(?np)) = ?maxW) graph ?a { ?version a gen:ResourceView ; dct:isVersionOf ?resource . } optional { graph ?a { ?version rdfs:label ?label } } optional { graph ?a { ?version dct:title ?titlex } } optional { graph ?a { ?version dct:description ?desc } } optional { graph ?a { ?version a ?vType } values (?vType ?typeName) { (gen:TabularView \"tabular\") (gen:ListView \"list\") (gen:ItemListView \"item list\") (gen:NanopubSetView \"nanopub set\") (gen:PlainParagraphView \"plain paragraph\") (gen:HeaderView \"header\") (gen:SvgView \"SVG\") (gen:NetworkView \"network\") (gen:ThreadView \"thread\") } } bind(exists { graph ?a { ?version a gen:QueryFormView } } as ?isForm) } group by ?resource ?registered ?np ?isForm } # One name per row: the title, or the label where there is none. A view without a # display type renders as a table, hence the tabular default. bind(coalesce(?title, ?viewLabel) as ?resource_label) bind(concat(coalesce(?typeVal, \"tabular\"), if(?isForm, \" + query form\", \"\")) as ?type) # The register_* columns are empty on listed rows, which hides the list action there. bind(if(?registered, \"\", \"⏳ not listed yet\") as ?status) bind(if(?registered, \"\", str(?resource)) as ?register_kind) bind(if(?registered, \"\", coalesce(?viewLabel, ?title)) as ?register_label) bind(if(?registered, \"\", coalesce(?description, ?viewLabel, ?title)) as ?register_description) } order by ?registered lcase(replace(str(?resource_label), \"^[^a-zA-Z0-9]+\", \"\"))""" . } 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-11-10T20:29:45Z"^^xsd:dateTime; dct:creator orcid:0000-0002-1267-0234; dct:license ; npx:embeds sub:list-maintained-views; npx:supersedes ; rdfs:label "List maintained views of a space"; skos:changeNote "Show one name per view instead of label and title side by side, which repeated the same text wherever the two are equal: the title, falling back to the label. Add a type column (tabular, list, nanopub set, ...), like the template type in the maintained-templates listing. Sort by the name without its leading emoji."; nt:wasCreatedFromProvenanceTemplate ; nt:wasCreatedFromPubinfoTemplate , , , ; nt:wasCreatedFromTemplate . sub:sig npx:hasAlgorithm "RSA"; npx:hasPublicKey "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwUtewGCpT5vIfXYE1bmf/Uqu1ojqnWdYxv+ySO80ul8Gu7m8KoyPAwuvaPj0lvPtHrg000qMmkxzKhYknEjq8v7EerxZNYp5B3/3+5ZpuWOYAs78UnQVjbHSmDdmryr4D4VvvNIiUmd0yxci47dTFUj4DvfHnGd6hVe5+goqdcwIDAQAB"; npx:hasSignature "I/0lzhcmfsASj0FH3bz3JZJictd70HZm7O+bzKC246xrLcfJQ3CqficeJJg/0vEhhAtjMSzWlf0n54lfQddRUTcxYInDjyVp8M7t2Y8x4aQOWfLFny7IqKkaQx0028iXtpkDA8HqAQR0V0I5P5xfFz7OJV3vyKXW5IvVLr2fH1I="; npx:hasSignatureTarget this:; npx:signedBy orcid:0000-0002-1267-0234 . }