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

knowledgepixels / nanodash / 27628876482

16 Jun 2026 03:30PM UTC coverage: 26.801% (-0.2%) from 26.963%
27628876482

Pull #484

github

web-flow
Merge 7c157c96b into 5b48046bd
Pull Request #484: Disambiguation notice for spaces with conflicting refs

1545 of 6777 branches covered (22.8%)

Branch coverage included in aggregate %.

3414 of 11726 relevant lines covered (29.11%)

4.28 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
        this(id, space, null);
×
80
    }
×
81

82
    /**
83
     * @param id            the Wicket markup id
84
     * @param space         the space whose About listings to render
85
     * @param effectiveRoot the root nanopub of the specific ref to scope the ref-aware views
86
     *                      (Info, Observers) to, or null to use the representative ref. See
87
     *                      docs/space-ref-identity.md.
88
     */
89
    public AboutSpacePanel(String id, Space space, String effectiveRoot) {
90
        super(id);
×
91

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

94
        // The info view leads the section (to the left of the presets). Its query is
95
        // scoped to a single space-ref, so it needs both the space IRI and the ref's
96
        // nanopub — bind them as separate params. When viewing a specific claimant the
97
        // effectiveRoot pins it to that ref's root definition.
98
        View infoView = View.get(SPACE_INFO_VIEW);
×
99
        Multimap<String, String> infoParams = ArrayListMultimap.create();
×
100
        infoParams.put("space", space.getId());
×
101
        infoParams.put("spaceNp", effectiveRoot != null ? effectiveRoot : space.getNanopubId());
×
102
        add(QueryResultTableBuilder.create("info", new QueryRef(infoView.getQuery().getQueryId(), infoParams), new ViewDisplay(infoView)).resourceWithProfile(space).id(space.getId()).contextId(space.getId()).build());
×
103

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

107
        View rolesView = View.get(SPACE_ROLES_VIEW);
×
108
        // Pass the space as resource/context so the roles view's per-entry action
109
        // button (publish a role assignment) renders with param_space prefilled,
110
        // mirroring the "+" button on the content tab's role list. postPublishTab
111
        // keeps the user on the About tab after publishing a role/assignment, so
112
        // they see the updated roles list (the presets/view-display views
113
        // intentionally fall through to the Content tab, where their effect shows).
114
        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());
×
115

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

119
        // "Users" section: admins/maintainers/members, then observers.
120

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

124
        View observersView = View.get(OBSERVERS_VIEW);
×
125
        // Drive the Observers table from the ref-scoped query that also includes un-introduced
126
        // self-declared observers (flagged via the headerless ⚠️ column), instead of the view's
127
        // own validated-only query. The view nanopub is left untouched. Falls back to the view's
128
        // IRI-keyed query when the ref root is unknown (pre-v3 data). See docs/space-ref-identity.md.
129
        String observersRefRoot = effectiveRoot != null ? effectiveRoot : space.getRefRootId();
×
130
        QueryRef observersQuery = (observersRefRoot != null && !observersRefRoot.isEmpty())
×
131
                ? new QueryRef(QueryApiAccess.LIST_SPACE_OBSERVERS_REF, "root_np", observersRefRoot)
×
132
                : new QueryRef(observersView.getQuery().getQueryId(), "space", space.getId());
×
133
        add(QueryResultTableBuilder.create("observers", observersQuery, new ViewDisplay(observersView)).build());
×
134

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

141
        View subSpacesView = View.get(SUB_SPACES_VIEW);
×
142
        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());
×
143

144
        View maintainedResourcesView = View.get(MAINTAINED_RESOURCES_VIEW);
×
145
        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());
×
146
    }
×
147

148
}
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