• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

knowledgepixels / nanodash / 27622310436

16 Jun 2026 01:49PM UTC coverage: 26.963% (+6.3%) from 20.697%
27622310436

Pull #483

github

web-flow
Merge dbba567c9 into 663f14f46
Pull Request #483: Space/resource About pages, ref-aware spaces, and magic query params

1542 of 6717 branches covered (22.96%)

Branch coverage included in aggregate %.

3407 of 11638 relevant lines covered (29.27%)

4.31 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
src/main/java/com/knowledgepixels/nanodash/component/AboutSpacePanel.java
1
package com.knowledgepixels.nanodash.component;
2

3
import com.google.common.collect.ArrayListMultimap;
4
import com.google.common.collect.Multimap;
5
import com.knowledgepixels.nanodash.QueryApiAccess;
6
import com.knowledgepixels.nanodash.View;
7
import com.knowledgepixels.nanodash.ViewDisplay;
8
import com.knowledgepixels.nanodash.domain.Space;
9
import org.apache.wicket.markup.html.panel.Panel;
10
import org.nanopub.extra.services.QueryRef;
11

12
/**
13
 * The "About" tab body for a space: its structure (assigned presets, roles, and
14
 * configured view displays; issue #302), its users (members and observers), and
15
 * its sub-units (sub-spaces and maintained resources). Rendered as views
16
 * (query result tables) rather than the live view content.
17
 */
18
public class AboutSpacePanel extends Panel {
19

20
    /**
21
     * The "ℹ️ Info" view: key-value facts about the space (type, alternative IDs,
22
     * dates, latest and root definition). Also shown on the Content tab; surfaced
23
     * here at the top of the About tab. Its query needs both the space IRI
24
     * ({@code space}) and the space's nanopub ({@code spaceNp}) so it can scope to
25
     * a single space-ref.
26
     */
27
    public static final String SPACE_INFO_VIEW = "https://w3id.org/np/RAIh3Cq4K99abRiL2xZphMYTjByvZYATK-d--dI3DD05g/space-info-view-kind";
28

29
    /**
30
     * View that lists all assigned view displays of a resource (built on the
31
     * get-view-displays query Nanodash uses internally). Shown on About tabs
32
     * instead of rendering the assigned views themselves.
33
     */
34
    public static final String VIEW_DISPLAYS_VIEW = "https://w3id.org/np/RA2Wxm80NAzOrXCjIZK9oVJ2vzbycuQtT3wLSGTX5vDVw/view-displays-view";
35

36
    /**
37
     * View listing the presets assigned to a resource (issue #302).
38
     */
39
    public static final String PRESET_ASSIGNMENTS_VIEW = "https://w3id.org/np/RA1kCQYXscKPY_qDvQ-WAKhoVomrTQLSt91JSD4Y03CKI/preset-assignments-view";
40

41
    /**
42
     * View listing a space's assigned roles as a table (role, schema:name, and a
43
     * count of how many of the space's users hold each role), built on the
44
     * list-space-roles query. The built-in Admin role is always the first row.
45
     */
46
    public static final String SPACE_ROLES_VIEW = "https://w3id.org/np/RActRjB7sOPegsSWdlJPNXvEfqEuomlO9HvjmBuXMqfQw/space-roles-view";
47

48
    /**
49
     * View listing a space's members (admins, maintainers, members) with their
50
     * highest role tier, built on the list-space-members query. Observer-tier
51
     * members are excluded.
52
     */
53
    public static final String MEMBERS_VIEW = "https://w3id.org/np/RAFmrcEqniX7mqrZQ8c4OCqjU-3wwKjLhE2glXAZKFNT0/space-members-view";
54

55
    /**
56
     * View listing a space's observers (members whose highest tier is observer,
57
     * i.e. holding no admin/maintainer/member role), built on the
58
     * list-space-observers query.
59
     */
60
    public static final String OBSERVERS_VIEW = "https://w3id.org/np/RA7uYe4WmsJCk3NaMTE8p0YofcMcRfjLyM8PGLaADkH18/space-observers-view";
61

62
    /**
63
     * View listing a space's direct sub-spaces with their types, built on the
64
     * list-sub-spaces query.
65
     */
66
    public static final String SUB_SPACES_VIEW = "https://w3id.org/np/RAoO4uYnSJXCHr0F5uVC5sYpkD4HOh-lsHQj4k3epqeH0/sub-spaces-view";
67

68
    /**
69
     * View listing the resources maintained by a space, built on the
70
     * list-maintained-resources query.
71
     */
72
    public static final String MAINTAINED_RESOURCES_VIEW = "https://w3id.org/np/RA4mk84QDZ4njO5N1sryJ5_wbyG7bAisL4BIAsNoISt-Y/maintained-resources-view";
73

74
    /**
75
     * @param id    the Wicket markup id
76
     * @param space the space whose About listings to render
77
     */
78
    public AboutSpacePanel(String id, Space space) {
79
        super(id);
×
80

81
        // "Structure" section: key-value info, presets, assigned roles, view displays.
82

83
        // The info view leads the section (to the left of the presets). Its query is
84
        // scoped to a single space-ref, so it needs both the space IRI and the
85
        // space's nanopub (the latest-definition NP) — bind them as separate params.
86
        View infoView = View.get(SPACE_INFO_VIEW);
×
87
        Multimap<String, String> infoParams = ArrayListMultimap.create();
×
88
        infoParams.put("space", space.getId());
×
89
        infoParams.put("spaceNp", space.getNanopubId());
×
90
        add(QueryResultTableBuilder.create("info", new QueryRef(infoView.getQuery().getQueryId(), infoParams), new ViewDisplay(infoView)).resourceWithProfile(space).id(space.getId()).contextId(space.getId()).build());
×
91

92
        View presetsView = View.get(PRESET_ASSIGNMENTS_VIEW);
×
93
        add(QueryResultTableBuilder.create("presets", new QueryRef(presetsView.getQuery().getQueryId(), "resource", space.getId()), new ViewDisplay(presetsView)).resourceWithProfile(space).id(space.getId()).contextId(space.getId()).build());
×
94

95
        View rolesView = View.get(SPACE_ROLES_VIEW);
×
96
        // Pass the space as resource/context so the roles view's per-entry action
97
        // button (publish a role assignment) renders with param_space prefilled,
98
        // mirroring the "+" button on the content tab's role list. postPublishTab
99
        // keeps the user on the About tab after publishing a role/assignment, so
100
        // they see the updated roles list (the presets/view-display views
101
        // intentionally fall through to the Content tab, where their effect shows).
102
        add(QueryResultTableBuilder.create("roles", new QueryRef(rolesView.getQuery().getQueryId(), "space", space.getId()), new ViewDisplay(rolesView)).resourceWithProfile(space).id(space.getId()).contextId(space.getId()).postPublishTab("about").build());
×
103

104
        View vdView = View.get(VIEW_DISPLAYS_VIEW);
×
105
        add(QueryResultTableBuilder.create("viewdisplays", new QueryRef(vdView.getQuery().getQueryId(), "resource", space.getId()), new ViewDisplay(vdView)).resourceWithProfile(space).id(space.getId()).contextId(space.getId()).build());
×
106

107
        // "Users" section: admins/maintainers/members, then observers.
108

109
        View membersView = View.get(MEMBERS_VIEW);
×
110
        add(QueryResultTableBuilder.create("members", new QueryRef(membersView.getQuery().getQueryId(), "space", space.getId()), new ViewDisplay(membersView)).build());
×
111

112
        View observersView = View.get(OBSERVERS_VIEW);
×
113
        // Drive the Observers table from the ref-scoped query that also includes un-introduced
114
        // self-declared observers (flagged via the headerless ⚠️ column), instead of the view's
115
        // own validated-only query. The view nanopub is left untouched. Falls back to the view's
116
        // IRI-keyed query when the ref root is unknown (pre-v3 data). See docs/space-ref-identity.md.
117
        String observersRefRoot = space.getRefRootId();
×
118
        QueryRef observersQuery = (observersRefRoot != null && !observersRefRoot.isEmpty())
×
119
                ? new QueryRef(QueryApiAccess.LIST_SPACE_OBSERVERS_REF, "root_np", observersRefRoot)
×
120
                : new QueryRef(observersView.getQuery().getQueryId(), "space", space.getId());
×
121
        add(QueryResultTableBuilder.create("observers", observersQuery, new ViewDisplay(observersView)).build());
×
122

123
        // "Sub-units" section: sub-spaces and maintained resources, side by side
124
        // (both views declare 6/12 width). resourceWithProfile/id/contextId let the
125
        // views' "add" actions pre-fill the new sub-space's IRI under this space's
126
        // namespace and this space as the maintainer, respectively; postPublishTab
127
        // returns the user here, where the new entry shows up.
128

129
        View subSpacesView = View.get(SUB_SPACES_VIEW);
×
130
        add(QueryResultListBuilder.create("subspaces", new QueryRef(subSpacesView.getQuery().getQueryId(), "space", space.getId()), new ViewDisplay(subSpacesView)).resourceWithProfile(space).id(space.getId()).contextId(space.getId()).postPublishTab("about").build());
×
131

132
        View maintainedResourcesView = View.get(MAINTAINED_RESOURCES_VIEW);
×
133
        add(QueryResultListBuilder.create("maintainedresources", new QueryRef(maintainedResourcesView.getQuery().getQueryId(), "space", space.getId()), new ViewDisplay(maintainedResourcesView)).resourceWithProfile(space).id(space.getId()).contextId(space.getId()).postPublishTab("about").build());
×
134
    }
×
135

136
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc