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

knowledgepixels / nanodash / 27145358627

08 Jun 2026 02:39PM UTC coverage: 20.682% (-0.3%) from 20.947%
27145358627

push

github

web-flow
Merge pull request #479 from knowledgepixels/feat/about-pages-478

Resource-page tabs, presets, and role-gated view actions (#478, #302)

1052 of 6429 branches covered (16.36%)

Branch coverage included in aggregate %.

2642 of 11432 relevant lines covered (23.11%)

3.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/page/ResourcePartPage.java
1
package com.knowledgepixels.nanodash.page;
2

3
import com.knowledgepixels.nanodash.ApiCache;
4
import com.knowledgepixels.nanodash.NanodashPageRef;
5
import com.knowledgepixels.nanodash.QueryApiAccess;
6
import com.knowledgepixels.nanodash.SpaceMemberRole;
7
import com.knowledgepixels.nanodash.Utils;
8
import com.knowledgepixels.nanodash.component.*;
9
import com.knowledgepixels.nanodash.domain.AbstractResourceWithProfile;
10
import com.knowledgepixels.nanodash.domain.IndividualAgent;
11
import com.knowledgepixels.nanodash.domain.MaintainedResource;
12
import com.knowledgepixels.nanodash.domain.Space;
13
import com.knowledgepixels.nanodash.domain.User;
14
import com.knowledgepixels.nanodash.repository.MaintainedResourceRepository;
15
import com.knowledgepixels.nanodash.repository.SpaceRepository;
16
import org.apache.wicket.Component;
17
import org.apache.wicket.extensions.ajax.markup.html.AjaxLazyLoadPanel;
18
import org.apache.wicket.markup.html.WebMarkupContainer;
19
import org.apache.wicket.markup.html.basic.Label;
20
import org.apache.wicket.markup.html.panel.EmptyPanel;
21
import org.apache.wicket.model.Model;
22
import org.apache.wicket.request.mapper.parameter.PageParameters;
23
import org.eclipse.rdf4j.model.IRI;
24
import org.eclipse.rdf4j.model.Statement;
25
import org.eclipse.rdf4j.model.util.Values;
26
import org.eclipse.rdf4j.model.vocabulary.DCTERMS;
27
import org.eclipse.rdf4j.model.vocabulary.RDF;
28
import org.eclipse.rdf4j.model.vocabulary.RDFS;
29
import org.eclipse.rdf4j.model.vocabulary.SKOS;
30
import org.nanopub.Nanopub;
31
import org.nanopub.extra.services.ApiResponse;
32
import org.nanopub.extra.services.QueryRef;
33

34
import java.util.ArrayList;
35
import java.util.HashSet;
36
import java.util.List;
37
import java.util.Set;
38

39
/**
40
 * This class represents a page for a resource part in the context of a maintained resource, space, or user.
41
 */
42
public class ResourcePartPage extends NanodashPage {
43

44
    /**
45
     * The mount path for this page.
46
     */
47
    public static final String MOUNT_PATH = "/part";
48

49
    /**
50
     * {@inheritDoc}
51
     */
52
    @Override
53
    public String getMountPath() {
54
        return MOUNT_PATH;
×
55
    }
56

57
    /**
58
     * Resource with profile (Space or MaintainedResource) object with the data shown on this page.
59
     */
60
    private AbstractResourceWithProfile resourceWithProfile;
61

62
    public ResourcePartPage(final PageParameters parameters) {
63
        super(parameters);
×
64

65
        final String id = parameters.get("id").toString();
×
66
        final String contextId = parameters.get("context").toString();
×
67
        final String nanopubId;
68
        String label = parameters.get("label").isEmpty() ? id.replaceFirst("^.*[#/]([^#/]+)$", "$1") : parameters.get("label").toString();
×
69
        String description = null;
×
70
        Set<IRI> classes = new HashSet<>();
×
71

72
        resourceWithProfile = MaintainedResourceRepository.get().findById(contextId);
×
73
        if (resourceWithProfile == null) {
×
74
            if (SpaceRepository.get().findById(contextId) != null) {
×
75
                resourceWithProfile = SpaceRepository.get().findById(contextId);
×
76
            } else if (IndividualAgent.isUser(contextId)) {
×
77
                resourceWithProfile = IndividualAgent.get(contextId);
×
78
            } else {
79
                throw new IllegalArgumentException("Not a resource, space, or user: " + contextId);
×
80
            }
81
        }
82

83
        QueryRef getDefQuery = new QueryRef(QueryApiAccess.GET_TERM_DEFINITIONS, "term", id);
×
84
        if (resourceWithProfile.getSpace() != null) {
×
85
            for (IRI userIri : resourceWithProfile.getSpace().getUsers()) {
×
86
                for (String pubkey : User.getUserData().getPubkeyHashes(userIri, true)) {
×
87
                    getDefQuery.getParams().put("pubkey", pubkey);
×
88
                }
×
89
            }
×
90
        } else {
91
            for (String pubkey : User.getUserData().getPubkeyHashes(Utils.vf.createIRI(contextId), true)) {
×
92
                getDefQuery.getParams().put("pubkey", pubkey);
×
93
            }
×
94
        }
95

96
        ApiResponse getDefResp = ApiCache.retrieveResponseSync(getDefQuery, false);
×
97
        if (getDefResp != null && !getDefResp.getData().isEmpty()) {
×
98
            nanopubId = getDefResp.getData().iterator().next().get("np");
×
99

100
            Nanopub nanopub = Utils.getAsNanopub(nanopubId);
×
101
            for (Statement st : nanopub.getAssertion()) {
×
102
                if (!st.getSubject().stringValue().equals(id)) {
×
103
                    continue;
×
104
                }
105
                if (st.getPredicate().equals(RDFS.LABEL)) {
×
106
                    label = st.getObject().stringValue();
×
107
                }
108
                if (st.getPredicate().equals(SKOS.DEFINITION) || st.getPredicate().equals(DCTERMS.DESCRIPTION) || st.getPredicate().equals(RDFS.COMMENT)) {
×
109
                    description = st.getObject().stringValue();
×
110
                }
111
                if (st.getPredicate().equals(RDF.TYPE) && st.getObject() instanceof IRI objIri) {
×
112
                    classes.add(objIri);
×
113
                }
114
            }
×
115
        } else {
×
116
            nanopubId = null;
×
117
        }
118
//        if (getDefResp == null || getDefResp.getData().isEmpty()) {
119
//            throw new RestartResponseException(ExplorePage.class, parameters);
120
//        }
121

122
        if (description != null) {
×
123
            add(new Label("description", description));
×
124
        } else {
125
            add(new Label("description").setVisible(false));
×
126
        }
127

128
        List<NanodashPageRef> breadCrumb;
129
        if (resourceWithProfile.getSpace() != null) {
×
130
            List<AbstractResourceWithProfile> superSpaces = resourceWithProfile.getSpace().getAllSuperSpacesUntilRoot();
×
131
            if (resourceWithProfile instanceof MaintainedResource) {
×
132
                superSpaces.add(resourceWithProfile.getSpace());
×
133
            }
134
            superSpaces.add(resourceWithProfile);
×
135
            breadCrumb = new ArrayList<>(superSpaces.stream().map(ss -> new NanodashPageRef(SpacePage.class, new PageParameters().add("id", ss.getId()), ss.getLabel())).toList());
×
136
        } else {
×
137
            breadCrumb = new ArrayList<>();
×
138
            breadCrumb.add(new NanodashPageRef(UserPage.class, new PageParameters().add("id", contextId), resourceWithProfile.getLabel()));
×
139
        }
140
        breadCrumb.add(new NanodashPageRef(ResourcePartPage.class, new PageParameters().add("id", id).add("context", contextId).add("label", label), label));
×
141
        NanodashPageRef[] breadCrumbArray = breadCrumb.toArray(new NanodashPageRef[0]);
×
142
        ResourceTabs.Tab activeTab = ResourceTabs.activeFromParam(parameters);
×
143
        add(new TitleBar("titlebar", this, null,
×
144
                breadCrumbArray
145
        ).setTabs(new ResourceTabs("tabs", "part", id, contextId, activeTab)));
×
146

147
        add(new JustPublishedMessagePanel("justPublishedMessage", parameters));
×
148

149
        add(new Label("pagetitle", label + " (resource part) | nanodash"));
×
150
        add(new Label("name", label));
×
151
        add(new Label("titlesuffix", ResourceTabs.titleSuffix(activeTab)));
×
152
        add(new ExternalLinkWithActionsPanel("id", Model.of(id), Model.of(label), nanopubId == null ? Values.iri(id) : Values.iri(nanopubId)));
×
153

154
        boolean showButton = false;
×
155
        if (resourceWithProfile instanceof IndividualAgent ia) {
×
156
            showButton = ia.isCurrentUser();
×
157
        } else if (resourceWithProfile.getSpace() != null) {
×
158
            showButton = SpaceMemberRole.isCurrentUserAdmin(resourceWithProfile.getSpace());
×
159
        } else if (resourceWithProfile instanceof Space s) {
×
160
            showButton = SpaceMemberRole.isCurrentUserAdmin(s);
×
161
        }
162
        add(new AddViewDisplayButton("addviewdisplay",
×
163
                "https://w3id.org/np/RAZg-r7oQjVZ3Ewy7pUzd9eINl6fCa3HGclTsDeRag5to",
164
                "latest",
165
                resourceWithProfile.getId(),
×
166
                resourceWithProfile.getId(),
×
167
                new PageParameters()
168
                        .set("part", id)
×
169
                        .set("refresh-upon-publish", resourceWithProfile.getId())
×
170
        ).setVisible(showButton));
×
171

172
        final String nanopubRef = nanopubId == null ? "x:" : nanopubId;
×
173
        WebMarkupContainer contentContainer = new WebMarkupContainer("contentContainer");
×
174
        add(contentContainer);
×
175
        if (activeTab == ResourceTabs.Tab.EXPLORE) {
×
176
            contentContainer.setVisible(false);
×
177
            add(new ExplorePanel("otherTab", id));
×
178
        } else if (activeTab == ResourceTabs.Tab.RAW) {
×
179
            contentContainer.setVisible(false);
×
180
            add(new DownloadRdfLinks("otherTab", "part", id, resourceWithProfile.getId()));
×
181
        } else {
182
            add(new EmptyPanel("otherTab").setVisible(false));
×
183
            if (resourceWithProfile.isDataInitialized()) {
×
184
                contentContainer.add(new ViewList("views", resourceWithProfile, id, nanopubRef, classes));
×
185
            } else {
186
                contentContainer.add(new AjaxLazyLoadPanel<Component>("views") {
×
187

188
                    @Override
189
                    public Component getLazyLoadComponent(String markupId) {
190
                        return new ViewList(markupId, resourceWithProfile, id, nanopubRef, classes);
×
191
                    }
192

193
                    @Override
194
                    protected boolean isContentReady() {
195
                        return resourceWithProfile.isDataInitialized();
×
196
                    }
197

198
                    @Override
199
                    public Component getLoadingComponent(String id) {
200
                        return new Label(id, "<div class=\"row-section\"><div class=\"col-12\">" + ResultComponent.getWaitIconHtml() + "</div></div>").setEscapeModelStrings(false);
×
201
                    }
202

203
                });
204
            }
205
        }
206
    }
×
207

208
    /**
209
     * Checks if auto-refresh is enabled for this page.
210
     *
211
     * @return true if auto-refresh is enabled, false otherwise
212
     */
213
    protected boolean hasAutoRefreshEnabled() {
214
        return true;
×
215
    }
216

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