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

knowledgepixels / nanodash / 27622721129

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

Pull #483

github

web-flow
Merge 73a4d0fe1 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/page/MaintainedResourcePage.java
1
package com.knowledgepixels.nanodash.page;
2

3
import com.knowledgepixels.nanodash.NanodashPageRef;
4
import com.knowledgepixels.nanodash.SpaceMemberRole;
5
import com.knowledgepixels.nanodash.component.*;
6
import com.knowledgepixels.nanodash.domain.AbstractResourceWithProfile;
7
import com.knowledgepixels.nanodash.domain.MaintainedResource;
8
import com.knowledgepixels.nanodash.domain.Space;
9
import com.knowledgepixels.nanodash.repository.MaintainedResourceRepository;
10
import org.apache.wicket.Component;
11
import org.apache.wicket.extensions.ajax.markup.html.AjaxLazyLoadPanel;
12
import org.apache.wicket.markup.html.WebMarkupContainer;
13
import org.apache.wicket.markup.html.basic.Label;
14
import org.apache.wicket.markup.html.panel.EmptyPanel;
15
import org.apache.wicket.model.IModel;
16
import org.apache.wicket.model.LoadableDetachableModel;
17
import org.apache.wicket.model.Model;
18
import org.apache.wicket.request.mapper.parameter.PageParameters;
19
import org.eclipse.rdf4j.model.util.Values;
20

21
import java.util.List;
22

23
/**
24
 * This class represents a page for a maintained resource.
25
 */
26
public class MaintainedResourcePage extends NanodashPage {
27

28
    /**
29
     * The mount path for this page.
30
     */
31
    public static final String MOUNT_PATH = "/resource";
32

33
    /**
34
     * {@inheritDoc}
35
     */
36
    @Override
37
    public String getMountPath() {
38
        return MOUNT_PATH;
×
39
    }
40

41
    /**
42
     * Id of the maintained resource shown on this page. Only the id is held in
43
     * the page state; the {@link MaintainedResource} itself is re-fetched from
44
     * the repository on every render via {@link #resourceModel}, so the page
45
     * tree never carries a serialized snapshot of singleton data.
46
     */
47
    private final String resourceId;
48

49
    /**
50
     * LDM that resolves {@link #resourceId} to the live {@link MaintainedResource} singleton.
51
     */
52
    private final IModel<MaintainedResource> resourceModel;
53

54
    public MaintainedResourcePage(final PageParameters parameters) {
55
        super(parameters);
×
56

57
        MaintainedResource resource = MaintainedResourceRepository.get().findById(parameters.get("id").toString());
×
58
        resourceId = resource.getId();
×
59
        resourceModel = new LoadableDetachableModel<MaintainedResource>() {
×
60
            @Override
61
            protected MaintainedResource load() {
62
                return MaintainedResourceRepository.get().findById(resourceId);
×
63
            }
64
        };
65
        resource.triggerDataUpdate();
×
66

67
        ResourceTabs.Tab activeTab = ResourceTabs.activeFromParam(parameters);
×
68

69
        List<AbstractResourceWithProfile> superSpaces = resource.getAllSuperSpacesUntilRoot();
×
70
        superSpaces.add(resource.getSpace());
×
71
        superSpaces.add(resource);
×
72
        add(new TitleBar("titlebar", this, null,
×
73
                superSpaces.stream().map(ss -> new NanodashPageRef(SpacePage.class, new PageParameters().add("id", ss.getId()), ss.getLabel())).toArray(NanodashPageRef[]::new)
×
74
        ).setTabs(new ResourceTabs("tabs", "resource", resource.getId(), activeTab)));
×
75

76
        add(new Label("pagetitle", resource.getLabel() + " (resource) | nanodash"));
×
77
        add(new Label("resourcename", resource.getLabel()));
×
78
        add(new Label("titlesuffix", ResourceTabs.titleSuffix(activeTab)));
×
79
        add(new ExternalLinkWithActionsPanel("id", Model.of(resource.getId()), Model.of(resource.getLabel()), Values.iri(resource.getNanopubId())));
×
80

81
        WebMarkupContainer contentContainer = new WebMarkupContainer("contentContainer");
×
82
        add(contentContainer);
×
83
        if (activeTab == ResourceTabs.Tab.CONTENT) {
×
84
            add(new EmptyPanel("otherTab").setVisible(false));
×
85
            if (resource.isDataInitialized()) {
×
86
                contentContainer.add(new ViewList("views", resource));
×
87
            } else {
88
                contentContainer.add(new AjaxLazyLoadPanel<Component>("views") {
×
89

90
                    @Override
91
                    public Component getLazyLoadComponent(String markupId) {
92
                        return new ViewList(markupId, resourceModel.getObject());
×
93
                    }
94

95
                    @Override
96
                    protected boolean isContentReady() {
97
                        return resourceModel.getObject().isDataInitialized();
×
98
                    }
99

100
                    @Override
101
                    public Component getLoadingComponent(String id) {
102
                        return new Label(id, "<div class=\"row-section\"><div class=\"col-12\">" + ResultComponent.getWaitIconHtml() + "</div></div>").setEscapeModelStrings(false);
×
103
                    }
104

105
                });
106
            }
107
        } else {
108
            contentContainer.setVisible(false);
×
109
            if (activeTab == ResourceTabs.Tab.ABOUT) {
×
110
                // The panel constructor resolves view nanopubs over the network when
111
                // they aren't freshly cached, which would block the initial page
112
                // render; the view-id list must mirror the panel's View.get calls.
113
                add(LazyContentPanel.of("otherTab", markupId -> new AboutResourcePanel(markupId, resourceModel.getObject()),
×
114
                        AboutResourcePanel.MAINTAINED_RESOURCE_INFO_VIEW, AboutSpacePanel.PRESET_ASSIGNMENTS_VIEW, AboutSpacePanel.VIEW_DISPLAYS_VIEW));
115
            } else if (activeTab == ResourceTabs.Tab.EXPLORE) {
×
116
                add(LazyContentPanel.of("otherTab", markupId -> new ExplorePanel(markupId, resourceId),
×
117
                        ReferencesPage.REFERENCES_VIEW));
118
            } else {
119
                add(new DownloadRdfLinks("otherTab", "resource", resource.getId()));
×
120
            }
121
        }
122
    }
×
123

124
    /**
125
     * Checks if auto-refresh is enabled for this page.
126
     *
127
     * @return true if auto-refresh is enabled, false otherwise
128
     */
129
    protected boolean hasAutoRefreshEnabled() {
130
        return true;
×
131
    }
132

133
    /**
134
     * {@inheritDoc}
135
     */
136
    @Override
137
    protected void onDetach() {
138
        resourceModel.detach();
×
139
        super.onDetach();
×
140
    }
×
141

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